<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.secondlife.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Fenchurch+Oh</id>
	<title>Second Life Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.secondlife.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Fenchurch+Oh"/>
	<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/wiki/Special:Contributions/Fenchurch_Oh"/>
	<updated>2026-06-22T14:22:55Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LSL_HTTP_server&amp;diff=1212773</id>
		<title>LSL HTTP server</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LSL_HTTP_server&amp;diff=1212773"/>
		<updated>2022-11-16T09:54:20Z</updated>

		<summary type="html">&lt;p&gt;Fenchurch Oh: Previous text &amp;quot;Testing this have it has been found that...&amp;quot; made ZERO sense.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header|ml=*}}&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
&lt;br /&gt;
This is the counterpart to [[llHTTPRequest]]. While [[llHTTPRequest]] enables [[Script|LSL scripts]] to request data from HTTP-accessible sources, HTTP-in enables outside sources to request data from [[Script|LSL scripts]] in Second Life. The key difference is that [[llHTTPRequest]] exchanges data when the script in SL wants; HTTP-in allows outside sources to determine when they need to communicate with [[Script|LSL scripts]] in SL.&lt;br /&gt;
&lt;br /&gt;
Prior to HTTP-in, similar functionality could be achieved by [[HTTP Polling|polling]] with [[llHTTPRequest]], [[llEmail]] and [[:Category:LSL_XML-RPC|XML-RPC]]. All three are cumbersome and the latter two have serious scalability bottlenecks.&lt;br /&gt;
&lt;br /&gt;
It is important to note that [[LSL HTTP server|LSL HTTP servers]] cannot use [[llSetContentType]] with [[CONTENT_TYPE_HTML]] for an [[llHTTPResponse]] except in very limited circumstances. See [[#Other_Limitations|Other Limitations]] for details.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;This section forms the [[:Category:LSL HTTP#Understanding_LSL_HTTP_Communications | Incoming]] HTTP pipeline.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Uses =&lt;br /&gt;
&lt;br /&gt;
* Easily get data from [[Script|LSL scripts]] to outside viewers, [[Script|LSL scripts]] or servers.&lt;br /&gt;
** Web front end for a visitor counter or other statistics accumulator.&lt;br /&gt;
* Easily get data into [[Script|LSL scripts]] from outside viewers, [[Script|LSL scripts]] or servers.&lt;br /&gt;
** A store with a web front end that communicates to an in-world object to exchange L$ and inventory items.&lt;br /&gt;
** Inworld game for which an external program handles the primary game logic that needs to manipulate inworld items.&lt;br /&gt;
* HUD UI when used with [[llSetContentType]]. See [[HTML HUD Demo]].&lt;br /&gt;
Gory Technical Details follow. Or jump straight to the [[LSL_http_server/examples | Script Examples]].&lt;br /&gt;
&lt;br /&gt;
= Script API =&lt;br /&gt;
&lt;br /&gt;
== Events ==&lt;br /&gt;
* &#039;&#039;&#039;[[http_request|http_request(key id, string method, string body)]]&#039;&#039;&#039;&lt;br /&gt;
: Event triggered when an URL is hit:&lt;br /&gt;
:* id is unique to this request&lt;br /&gt;
:* Supported methods are &amp;lt;code&amp;gt;&amp;quot;GET&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;POST&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;PUT&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;DELETE&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:* body: The body of the request.&lt;br /&gt;
: Event also triggered with response to [[llRequestURL]] and [[llRequestSecureURL]]&lt;br /&gt;
:* id matches the key returned by [[llRequestURL]] or [[llRequestSecureURL]]&lt;br /&gt;
:* method == [[URL_REQUEST_GRANTED]] for success, [[URL_REQUEST_DENIED]] for failure to get an URL&lt;br /&gt;
:* body is the public URL. If unable to get a public URL body will be empty.&lt;br /&gt;
* &#039;&#039;&#039;[[Changed|changed(integer change)]]&#039;&#039;&#039;&lt;br /&gt;
:* [[CHANGED_REGION_START]]: New [[changed]] [[event]] triggered on region startup.&lt;br /&gt;
:* [[CHANGED_REGION]]: New [[changed]] [[event]] triggered when crossing regions or teleporting. Please read [[CHANGED_REGION]] for more info.&lt;br /&gt;
:* [[CHANGED_TELEPORT]]: New [[changed]] [[event]] triggered when the avatar teleports. Please read [[CHANGED_TELEPORT]] for more info.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
{{LSL Function/Head&lt;br /&gt;
|func_id=345|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llRequestURL&lt;br /&gt;
|func_desc=Requests one HTTP:// url for use by the script. The [[http_request]] [[event]] is triggered with the result of the request. HTTP-in uses port 12046.&lt;br /&gt;
|return_type=key|return_text=that is the handle used for identifying the result in the [[http_request]] [[event]].&lt;br /&gt;
|func_footer&lt;br /&gt;
|caveats=none&lt;br /&gt;
}}&lt;br /&gt;
{{LSL Function/Head&lt;br /&gt;
|func_id=346|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llRequestSecureURL&lt;br /&gt;
|func_desc=Requests one HTTPS:// (SSL) url for use by the script. The [[http_request]] [[event]] is triggered with the result of the request. HTTPS-in uses port 12043.&lt;br /&gt;
|return_type=key|return_text=that is the handle used for identifying the result in the [[http_request]] [[event]].&lt;br /&gt;
|func_footer&lt;br /&gt;
|caveats=none&lt;br /&gt;
}}&lt;br /&gt;
{{LSL Function/Head&lt;br /&gt;
|func_id=347|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llReleaseURL&lt;br /&gt;
|p1_type=string|p1_name=url|p1_desc=URL to release&lt;br /&gt;
|func_desc=Releases the specified URL, it will no longer be usable.&lt;br /&gt;
|func_footer&lt;br /&gt;
|caveats=none&lt;br /&gt;
}}&lt;br /&gt;
{{LSL Function/Head&lt;br /&gt;
|func_id=348|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llHTTPResponse&lt;br /&gt;
|p1_type=key|p1_name=request_id|p1_desc=A valid HTTP request key&lt;br /&gt;
|p2_type=integer|p2_name=status|p2_desc=[http://en.wikipedia.org/wiki/List_of_HTTP_status_codes HTTP_Status] (200, 400, 404, etc)&lt;br /&gt;
|p3_type=string|p3_name=body|p3_desc=Contents of the response.&lt;br /&gt;
|func_desc=Responds to {{LSLP|request_id}} with {{LSLP|status}} and {{LSLP|body}}.&lt;br /&gt;
|func_footer=The response need not be made inside the [[http_request]] [[event]] but if it does not happen in a timely fashion the request will time out (within 25 seconds).&lt;br /&gt;
|caveats=none&lt;br /&gt;
}}&lt;br /&gt;
{{LSL Function/Head&lt;br /&gt;
|func_id=344|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llGetFreeURLs&lt;br /&gt;
|return_type=integer|return_text=that is the number of available URLs.&lt;br /&gt;
|caveats=none&lt;br /&gt;
}}&lt;br /&gt;
{{LSL Function/Head&lt;br /&gt;
|func_id=349|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llGetHTTPHeader&lt;br /&gt;
|p1_type=key|p1_name=request_id|p1_desc=A valid HTTP request key&lt;br /&gt;
|p2_type=string|p2_name=header|p2_desc=Lower case header value name&lt;br /&gt;
|return_type=string|return_text=that is the value for {{LSLP|header}} for {{LSLP|request_id}}.&lt;br /&gt;
|func_footer=Returns an empty [[string]] if the {{LSLP|header}} is not found or if the headers can no longer be accessed. Headers can only be accessed before [[llHTTPResponse]] is called and with-in the first 30 seconds after the [[http_request]] [[event]] is queued.&lt;br /&gt;
&lt;br /&gt;
====Generated Headers====&lt;br /&gt;
These headers are automatically generated by the simulator, they were not actually sent by the requesting client. They supply information about the request to make parsing easier.&lt;br /&gt;
&lt;br /&gt;
Sample URL: [https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322/foo/bar?arg=gra {{HoverTextStyle|style=color:green;|&amp;lt;nowiki&amp;gt;https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322&amp;lt;/nowiki&amp;gt;|2={{String|x-script-url}} = {{String|https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322}}}}{{HoverTextStyle|style=color:blue;|/foo/bar|2={{String|x-path-info}} = {{String|/foo/bar}}}}?{{HoverTextStyle|style=color:red;|1=arg=gra|2={{String|x-query-string}} = {{String|1=arg=gra}}}}]&lt;br /&gt;
&lt;br /&gt;
{{{!}} class=&amp;quot;lltable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! header&lt;br /&gt;
! description&lt;br /&gt;
! example&lt;br /&gt;
{{!}}-&lt;br /&gt;
{{!}} style=&amp;quot;white-space: nowrap;&amp;quot; {{!}} &amp;quot;x-script-url&amp;quot;&lt;br /&gt;
{{!}} The base url, as originally received from [[llRequestURL]]/[[llRequestSecureURL]]&lt;br /&gt;
{{!}} &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322&amp;lt;/nowiki&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
{{!}}-&lt;br /&gt;
{{!}} style=&amp;quot;white-space: nowrap;&amp;quot; {{!}} &amp;quot;x-path-info&amp;quot;&lt;br /&gt;
{{!}} Any trailing path information from the requested url&lt;br /&gt;
{{!}} &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;/foo/bar&amp;lt;/font&amp;gt;&lt;br /&gt;
{{!}}-&lt;br /&gt;
{{!}} style=&amp;quot;white-space: nowrap;&amp;quot; {{!}} &amp;quot;x-query-string&amp;quot;&lt;br /&gt;
{{!}} Any query arguments, the text past the first &amp;quot;?&amp;quot; in the url&lt;br /&gt;
{{!}} &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;arg=gra&amp;lt;/font&amp;gt;&lt;br /&gt;
{{!}}-&lt;br /&gt;
{{!}} style=&amp;quot;white-space: nowrap;&amp;quot; {{!}} &amp;quot;x-remote-ip&amp;quot;&lt;br /&gt;
{{!}} IP address of the host that made the request&lt;br /&gt;
{{!}}&lt;br /&gt;
{{!}}}&lt;br /&gt;
&lt;br /&gt;
====Common Headers====&lt;br /&gt;
&lt;br /&gt;
{{{!}} class=&amp;quot;lltable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! header&lt;br /&gt;
! description&lt;br /&gt;
! example&lt;br /&gt;
{{!}}-&lt;br /&gt;
{{!}} style=&amp;quot;white-space: nowrap;&amp;quot; {{!}} &amp;quot;user-agent&amp;quot;&lt;br /&gt;
{{!}} The user-agent header as reported by the requester&lt;br /&gt;
{{!}}&lt;br /&gt;
{{!}}}&lt;br /&gt;
&lt;br /&gt;
====[[llHTTPRequest]] Headers====&lt;br /&gt;
{{LSL_Constants/HTTP_Headers|lower-case=*}}&lt;br /&gt;
|caveats=none&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= URL Lifetime Limitations =&lt;br /&gt;
* URLs are &#039;&#039;&#039;temporary&#039;&#039;&#039;!&lt;br /&gt;
* URLs will be lost in the following cases, all detectable by the script events listed with them.&lt;br /&gt;
** On object derez/rez: [[on_rez]]&lt;br /&gt;
** On script save/reset: &#039;&#039;[[default]] [[state_entry]] (trickier in multi-state [[Script|LSL scripts]])&lt;br /&gt;
** On region cross or TP(attachments): [[changed]] {{LSLGC|Events|event}}, [[CHANGED_REGION]] and [[CHANGED_TELEPORT]]. Testing the latter event, it has been found that teleports within a region DO NOT cause a URL to be lost, therefore you do not need to request a new URL on [[CHANGED_TELEPORT]], because [[CHANGED_REGION]] will handle a teleport to a different region. If you choose to request a URL after a teleport, it is recommended to release the old URL to be sure you don&#039;t have too many used. (Stone Tremont Aug 8th 2010)&lt;br /&gt;
** On region restart: [[changed]] [[event]], flag [[CHANGED_REGION_START]]&lt;br /&gt;
* When urls are &#039;lost&#039; it means that all public urls for that script are gone, new ones will need to be requested and the new urls will &#039;&#039;&#039;not&#039;&#039;&#039; resemble the old ones.&lt;br /&gt;
* Maintaining persistent URLs will require building or using an external service similar to how [http://en.wikipedia.org/wiki/Dynamic_DNS Dynamic DNS] services work for tying domain names to dynamic IP addresses.&lt;br /&gt;
&lt;br /&gt;
Contributed HTTP-in URL mapping implementations and services:&lt;br /&gt;
* A Dynamic DNS service running on Google App Engine (contributed as an example) can be found in the forums [http://wiki.secondlife.com/wiki/User:Darien_Caldwell/HTTP-DNS here].&lt;br /&gt;
* Yet another one, running on GAE, with password protected and private domains. http://wiki.secondlife.com/wiki/Public_Object_DNS&lt;br /&gt;
* The [http://www.silverday.net/sqndns SilverDay ObjectDNS] is an easy to use dns-mapping-service with many configurable options (password protection, write protection, etc.) and an optional web-interface. The [[Script|LSL scripts]] are available here on the wiki (LSL-Script Library/[[Silverday ObjectDNS]]).&lt;br /&gt;
&lt;br /&gt;
= Resource Limitations =&lt;br /&gt;
* There are a limited number of URLs available in each [[region]], split by land ownership exactly like prim limits.&lt;br /&gt;
** Use [[llGetFreeURLs]] to get the exact number of available URLs for the script.&lt;br /&gt;
** The number of allowed URLs is the same as the number of allowed [[prim|prims]] on the [[Land#Parcel|parcel]] the [[object]] is over.&lt;br /&gt;
**: &#039;&#039;Object owner does not matter, all objects over a [[Land#Parcel|parcel]] will use the resource pool for that [[Land#Parcel|parcel]].&#039;&#039;&lt;br /&gt;
**: &#039;&#039;Like [[prim|prims]], all the [[Land#Parcel|parcels]] owned by the same owner and in the same [[region]] share the same pool of resources.&#039;&#039;&lt;br /&gt;
**: &#039;&#039;If you have two [[Land#Parcel|parcels]] in a [[region]] that each support 100 URLs, then you could use all 200 in object(s) on a single [[Land#Parcel|parcel]].&#039;&#039;&lt;br /&gt;
** The [[region]]&#039;s [[object]] bonus factor does not apply to available URLs.&lt;br /&gt;
**: &#039;&#039;If a [[Land#Parcel|parcel]] has a max of 300 [[prim|prims]] in a [[region]] with a 2x bonus factor there will only be 150 urls allowed.&#039;&#039;&lt;br /&gt;
* Each resident has their own unique pool of available URLs with a max of 38 URLs per resident.&lt;br /&gt;
** This is 1 per attachment point, but all 38 could be used by a single attachment for example.&lt;br /&gt;
* Vehicles are special and lazily moved to resident pools by the following logic:&lt;br /&gt;
** Any [[object]] that has a resident sitting on it is a &#039;vehicle&#039;&lt;br /&gt;
** Vehicles will use the url resources from the [[Land#Parcel|parcel]] they are over until the cross a [[Land#Parcel|parcel]] border.&lt;br /&gt;
**: &#039;&#039;Specifically this prevents anyone from breaking your vending machine by sitting on it and making it a &#039;vehicle&#039;.&#039;&#039;&lt;br /&gt;
** When any [[object]] using URL resources with a resident sitting on it crosses a [[Land#Parcel|parcel]] boundary the resources will switch to the first sitting resident with enough resources. If no sitting agents have enough resources then the resources from the [[Land#Parcel|parcel]] being moved onto will be used. If even then there are not enough resources to use then the vehicle will be blocked from moving.&lt;br /&gt;
**: &#039;&#039;In short we do everything we can to find a pool to host the resources needed by the vehicle, but will block movement if we can&#039;t.&#039;&#039;&lt;br /&gt;
* Parcel Sale: When a [[Land#Parcel|parcel]] is sold such that it changes the total available URLs in the [[region]] for either resident (seller or buyer) such that more URLs are being used than are available some objects will be returned.&lt;br /&gt;
** The objects returned will be from youngest [[object]] to oldest [[object]] of those using URLs in each category in order of [[object]] category: Temporary, Other, Group, Owner, Selected/Sat upon.&lt;br /&gt;
**: &#039;&#039;The &#039;&#039;&#039;only&#039;&#039;&#039; time objects are possibly returned is when [[Land#Parcel|parcels]] change owner, and only if more resources are being used than allowed.&#039;&#039;&lt;br /&gt;
**: &#039;&#039;We return youngest temporary objects before older temporary objects before younger &#039;other&#039; (owned by non-group, non-[[Land#Parcel|parcel]]-owner) objects etc.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Other Limitations =&lt;br /&gt;
* Size of the body of requests on the &#039;&#039;&#039;[[:Category:LSL HTTP#Understanding_LSL_HTTP_Communications | Incoming pipeline]]&#039;&#039;&#039; will be [[limit]]ed to 2k [[bytes]], and cannot currently be changed.&lt;br /&gt;
* Size of headers of requests will be limited to 255 bytes per header, not total.&lt;br /&gt;
* The size of responses to requests is not currently limited, but this is subject to review during testing.&lt;br /&gt;
* By default the content type of the returned data is always &amp;lt;code&amp;gt;&amp;quot;text/plain; charset=utf-8&amp;quot;&amp;lt;/code&amp;gt;, this however can be changed via [[llSetContentType]] for all subsequent responses via [[llHTTPResponse]].&lt;br /&gt;
* There is a cap of 64 in flight requests per script. This is based on the maximum number of pending [[event|events]] in LSL. After hitting the 64 request limit, the simulator cap server returns &amp;lt;code&amp;gt;{{String|503 Service Unavailable}}&amp;lt;/code&amp;gt; to the inbound request.&lt;br /&gt;
* &#039;&#039;We may throttle the rate we accept hits at the CAP server level as well. This is possible, but has not yet been decided.&#039;&#039;&lt;br /&gt;
* HTML can be used to in-client browser, including media on a prim, with some restrictions. See [[llSetContentType]] and [[CONTENT_TYPE_HTML]] for further details.&lt;br /&gt;
* If making a parser, remember that you should probably restrict access to only Linden Lab HTML URLs as to not have your bandwith stolen. See [[Simulator_IP_Addresses]] for details.&lt;br /&gt;
* It is important to note that when appending a query string to a cap URL there &#039;&#039;&#039;MUST&#039;&#039;&#039; be a trailing slash between the cap guid and the query string token &amp;lt;code&amp;gt;&amp;quot;?&amp;quot;&amp;lt;/code&amp;gt;. For example: [https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322?arg=gra {{HoverTextStyle|style=color:green;|&amp;lt;nowiki&amp;gt;https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322&amp;lt;/nowiki&amp;gt;|2={{String|x-script-url}} = {{String|https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322}}}}?{{HoverTextStyle|style=color:red;|1=arg=gra|2={{String|x-query-string}} = {{String|1=arg=gra}}}}] will return a 500 HTTP status {{Wikipedia|List_of_HTTP_status_codes#5xx_Server_Error|Server Error code}}, but [https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322/?arg=gra {{HoverTextStyle|style=color:green;|&amp;lt;nowiki&amp;gt;https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322&amp;lt;/nowiki&amp;gt;|2={{String|x-script-url}} = {{String|https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322}}}}{{HoverTextStyle|style=color:blue;|/|2={{String|x-path-info}} = {{String|/}}}}?{{HoverTextStyle|style=color:red;|1=arg=gra|2={{String|x-query-string}} = {{String|1=arg=gra}}}}] will succeed.&lt;br /&gt;
&lt;br /&gt;
= Links =&lt;br /&gt;
* [[LSL_http_server/examples | Script Examples]]&lt;br /&gt;
* [[LSL_http_server/design | Design Document]]&lt;br /&gt;
* Design Jira:{{jira|SVC-1086}}&lt;br /&gt;
&lt;br /&gt;
{{LSLC|HTTP}}&lt;br /&gt;
{{LSLC|Communications}}&lt;/div&gt;</summary>
		<author><name>Fenchurch Oh</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlSetRemoteScriptAccessPin&amp;diff=1209929</id>
		<title>LlSetRemoteScriptAccessPin</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlSetRemoteScriptAccessPin&amp;diff=1209929"/>
		<updated>2021-03-04T20:41:25Z</updated>

		<summary type="html">&lt;p&gt;Fenchurch Oh: Typo correction.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Function&lt;br /&gt;
|func_id=252|func_sleep=0.2|func_energy=10.0&lt;br /&gt;
|func=llSetRemoteScriptAccessPin&lt;br /&gt;
|p1_type=integer|p1_name=pin|p1_desc=zero disables (ie [[llRemoteLoadScriptPin]] will fail), non-zero enables.&lt;br /&gt;
|func_desc=Allows a prim to have scripts remotely loaded via [[llRemoteLoadScriptPin]] when it is passed the correct pin and the prim is set mod.&lt;br /&gt;
|func_footnote&lt;br /&gt;
|spec&lt;br /&gt;
|caveats=*A prim has only one pin for remotely loading scripts.&lt;br /&gt;
**By changing the pin, a script can deny other scripts the ability to load scripts into the prim.&lt;br /&gt;
***This could result in unintentionally breaking a products ability to be updated by an upstream creator.&lt;br /&gt;
***This can be used to intentionally stop an upstream creator from updating a product.&lt;br /&gt;
|constants&lt;br /&gt;
|examples&lt;br /&gt;
|helpers&lt;br /&gt;
|also_functions={{LSL DefineRow||[[llRemoteLoadScriptPin]]|Used to load a script into a remote prim}}&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|notes&lt;br /&gt;
|cat1=Script&lt;br /&gt;
|cat2&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
|}}&lt;/div&gt;</summary>
		<author><name>Fenchurch Oh</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Rotation&amp;diff=1209891</id>
		<title>Rotation</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Rotation&amp;diff=1209891"/>
		<updated>2021-02-13T00:03:34Z</updated>

		<summary type="html">&lt;p&gt;Fenchurch Oh: Removed link to domain isner.com - page no longer exists.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header|ml=*}}{{RightToc}}&lt;br /&gt;
==Rotation==&lt;br /&gt;
&lt;br /&gt;
A [[rotation]] is a data {{LSLGC|Types|type}} that contains a set of four [[float]] vlaues.&lt;br /&gt;
&lt;br /&gt;
Each element can be accessed individually by appending &amp;lt;code&amp;gt;.x&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.y&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.z&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;.s&amp;lt;/code&amp;gt; to the variable name.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;rotation rot;&lt;br /&gt;
float x = rot.x;&lt;br /&gt;
float y = rot.y;&lt;br /&gt;
float z = rot.z;&lt;br /&gt;
float s = rot.s;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The LSL &#039;&#039;&#039;rotation&#039;&#039;&#039; type is one of several ways to represent an orientation in 3D.  (Note that we try to write the type name in &#039;&#039;&#039;bold&#039;&#039;&#039;.)&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;rotation&#039;&#039;&#039; can be viewed as a discrete twist in three dimensional space, and the orientation of an object is how much it has been twisted around from whichever axes we are using - normally the region&#039;s axes.&lt;br /&gt;
&lt;br /&gt;
It is  a mathematical object called a [[quaternion]].  You can think of a quaternion as four numbers, three of which represent the direction an object is facing and a fourth that represents the object&#039;s banking left or right around that direction. The main advantage of using &lt;br /&gt;
quaternions is that they are not susceptible to [http://en.wikipedia.org/wiki/Gimbal_Lock gimbal lock]. &lt;br /&gt;
For the complex inner workings of quaternion mathematics, see {{LSLG|quaternion}}. &lt;br /&gt;
For a list of functions and events related to rotations see {{LSLG|LSL Rotation Synopsis}}.&lt;br /&gt;
There is also information about causing  textures to rotate in {{LSLG|texture}}s.&lt;br /&gt;
&lt;br /&gt;
Rotations are often regarded a very confusing subject, where scripters use trial-and-error to get it right. The reasons for this confusion are:&lt;br /&gt;
* Nobody really knows what a [[quaternion]] is, or how to think about it (not entirely true, the brain just isn&#039;t good at thinking in 4 geometric dimensions).&lt;br /&gt;
* There are actually several different types of vectors (&#039;dir&#039;, &#039;vec&#039; and &#039;pos&#039;) that need to acted upon differently.&lt;br /&gt;
* The order in which translation and rotations need to be applied can vary from case to case.&lt;br /&gt;
* There is confusion about the difference between an applied rotation and the rotation &#039;offset&#039; between coordinate systems.&lt;br /&gt;
To master rotations it is therefore essential to use a good naming system for your variables. Such a system is described in the excellent article [[User:Timmy_Foxclaw/About_Coordinate_Systems_and_Rotations|About Coordinate Systems and Rotations]] by [[User:Timmy_Foxclaw|Timmy Foxclaw]].&lt;br /&gt;
&lt;br /&gt;
==Other representations==&lt;br /&gt;
===Euler vector===&lt;br /&gt;
Another way to represent a 3D angle is using three numbers, &amp;lt;X, Y, Z&amp;gt;, which represent the amount  which the object is rotated around each axis.  This is used in the Edit window, for example, and is generally easy for people to visualize.  It is easy to adjust the Rotation &amp;lt;x, y, z&amp;gt; numbers in the Edit window and see how the object behaves.  Note that in the Edit window, the numbers are in degrees, that is, a right angle is 90.&lt;br /&gt;
&lt;br /&gt;
In LSL, these three angles are expressed in [[radians]] instead of degrees, that is, a right angle is PI/2.  (A radian is sort of a very fat degree.)&lt;br /&gt;
Note that these three numbers are a &#039;&#039;&#039;vector&#039;&#039;&#039; type and not a &#039;&#039;&#039;rotation&#039;&#039;&#039; type, though it can represent the same information.  This is called the &#039;&#039;Euler&#039;&#039; representation of a 3D angle.  &#039;&#039;&#039;In LSL the rotation around z is done first, then around y, and finally around x&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Axis plus Angle===&lt;br /&gt;
In this method you define an axis of rotation, like defining the axis about which the earth spins, and use that together with the angle of rotation about the axis, which defines the amount of turn, to give the &#039;&#039;&#039;rotation&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
So if you want to define a &#039;&#039;&#039;rotation&#039;&#039;&#039; about an axis at 45 degrees in the x-y plane (North East in region coordinates), you&#039;d need to point the axis with the same amount of x and y, but with no z.  The axis could be &amp;lt;1.0, 1.0, 0.0&amp;gt;.  The absolute size of the numbers defining the axis don’t matter in this representation; &amp;lt;2.0, 2.0, 0.0&amp;gt; would work just as well.  The angle of rotation is a separate number given in radians, eg. PI/3 = 60 degrees.  Together they define a global &#039;&#039;&#039;rotation&#039;&#039;&#039; of 60 degrees about the North East axis.&lt;br /&gt;
&lt;br /&gt;
Like a quaternion Axis plus Angle uses four numbers, but it doesn&#039;t need to be &amp;quot;normalized&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===FWD, LEFT, UP===  &lt;br /&gt;
Another way to represent the same 3D angle is to use three vectors, showing what the front is pointing at (fwd), what the top is pointing at (up), and what the left side is pointing at (left).  Actually, only two of the three are needed, because any two determines the third.  &lt;br /&gt;
&lt;br /&gt;
For good reasons, such as being able to easily combine rotations, the four number version, the quaternion &#039;&#039;&#039;rotation&#039;&#039;&#039;, is better, though perhaps harder for a beginner to grasp. Fortunately it&#039;s very seldom necessary to do anything with the actual internal representation of &#039;&#039;rotations&#039;&#039; and there are functions for converting easily back and forth between the three LSL types, and between degrees and radians.&lt;br /&gt;
&lt;br /&gt;
==Right hand rule==&lt;br /&gt;
In LSL all rotations are done according to the &#039;&#039;&#039;right hand rule&#039;&#039;&#039;. With your right hand, extend the first finger in the direction of the positive direction of the x-axis. Extend your second finger at right angles to your first finger, it will point along the positive y-axis, and your thumb, extended at right angles to both will point along the positive z-axis. When you&#039;re editing an object, the three colored axis arrows point in the positive direction for each axis (X: red, Y: green, Z: blue).&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Right_hand_rule&lt;br /&gt;
&lt;br /&gt;
Now, don&#039;t remove your right hand just yet, there is another use for it, determining the direction of a positive rotation. Make a fist with your right hand, thumb extended and pointing in the positive direction of the axis you are interested in. Your fingers curl around in the direction of positive rotation. Rotations around the X, Y, and Z axis are often referred to as Roll, Pitch, and Yaw, particularly for vehicles.&lt;br /&gt;
&lt;br /&gt;
[http://en.wikipedia.org/wiki/Tait-Bryan_angles Roll Pitch Yaw]&lt;br /&gt;
&lt;br /&gt;
== Combining Rotations ==&lt;br /&gt;
&#039;&lt;br /&gt;
Suppose you have two rotations.  &#039;&#039;r1&#039;&#039; is rotate 90 degrees to the left, and &#039;&#039;r2&#039;&#039; is rotate 30 degrees to the right.  (Any rotations will work; these are just an example.)&lt;br /&gt;
You can combine &#039;&#039;r1&#039;&#039; and &#039;&#039;r2&#039;&#039; to make &#039;&#039;r3&#039;&#039; using the &#039;&#039;&#039;*&#039;&#039;&#039; operator.  It doesn&#039;t really multiply them, it &#039;&#039;composes&#039;&#039; them.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
rotation r3 = r1 * r2;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
The result in this case is that &#039;&#039;r3&#039;&#039; means rotate 60 degrees to the left.&lt;br /&gt;
&lt;br /&gt;
In other words, to combine &#039;&#039;&#039;rotations&#039;&#039;&#039;, you use the &#039;&#039;&#039;multiply&#039;&#039;&#039; and &#039;&#039;&#039;divide&#039;&#039;&#039; operators. Don&#039;t try to use addition or subtraction operators on &#039;&#039;&#039;rotations&#039;&#039;&#039;, as they will not do what you expect. The &#039;&#039;&#039;multiply&#039;&#039;&#039; operation applies the rotation in the positive direction, the &#039;&#039;&#039;divide&#039;&#039;&#039; operation does a negative rotation. You can also negate a rotation directly, just negate the s component, e.g. X.s = -X.s.&lt;br /&gt;
&lt;br /&gt;
Unlike other types such as {{LSLG|float}}, the order in which the operations are done, &lt;br /&gt;
[http://en.wikipedia.org/wiki/Commutative non-commutative], is important.&lt;br /&gt;
The reason for this is simple: the order you do rotations in is important in RL. For example, if you had a dart with four feathers, started from rotation &amp;lt;0, 0, 0&amp;gt; with its tail on the origin, it would lie on the X axis with its point aimed in the positive X direction, its feathers along the Z and Y axes, and the axes of the dart and the axes of the world would be aligned. We&#039;re going to rotate it 45 degrees around X and 30 degrees around Y, but in different orders.&lt;br /&gt;
&lt;br /&gt;
First, after rotating 45 deg around X the dart would still be on the X axis, unmoved, just turned along its long axis, so the feathers would be at 45 deg to the axes. Then rotating 30 deg around Y would move it in the XZ plane to point down 30 deg from the X axis (remember the right hand rule for rotations means a small positive rotation around Y moves the point down). The dart winds up pointing 30 deg down, in the same vertical plane it started in, but turned around its own long axis so the feathers are no longer up and down.&lt;br /&gt;
&lt;br /&gt;
If you did it the other way, first rotating 30 deg in Y, the dart would rotate down in the XZ plane, but notice that it no longer is on the X axis; its X axis and the world&#039;s aren&#039;t aligned any more. Now a 45 degree rotation around the X axis would pivot the dart around its tail, the point following a 30 deg cone whose axis is along the positive world X axis, for 45 degrees up and to the right. If you were looking down the X axis, it would pivot from pointing 30 deg below the X axis, up and to the right, out of the XZ plane, to a point below the 1st quadrant in the XY plane, its feathers rotating as it went.&lt;br /&gt;
&lt;br /&gt;
Clearly this is a different result from the first rotation, but the order of rotation is the only thing changed.&lt;br /&gt;
&lt;br /&gt;
To do a constant rotation you need to define a &#039;&#039;&#039;rotation&#039;&#039;&#039; value which can be done by creating a {{LSLG|vector}} with the X, Y, Z angles in radians as components (called an Euler angle), then converting that to a &#039;&#039;&#039;rotation&#039;&#039;&#039; by using the {{LSLG|llEuler2Rot}} function. To go from a rotation to an Euler angle {{LSLG|vector}} use {{LSLG|llRot2Euler}}.&lt;br /&gt;
&lt;br /&gt;
If you want an axial rotation you insert the axis of rotation and the turn angle into the {{LSLG|llAxisAngle2Rot}} function, and this will return the &#039;&#039;&#039;rotation&#039;&#039;&#039;. To go from a rotation back to axis and angle, use {{LSLG|llRot2Axis}} and {{LSLG|llRot2Angle}} respectively.&lt;br /&gt;
&lt;br /&gt;
You can alternately create the native rotation directly: the real part is the cosine of half the angle of rotation, and the vector part is the normalized axis of rotation multiplied by the sine of half the angle of rotation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; angles in LSL are in radians, not degrees, but you can easily convert by using the built-in constants [[#RAD_TO_DEG|RAD_TO_DEG]] and [[#DEG_TO_RAD|DEG_TO_RAD]]. For a 30 degree &#039;&#039;&#039;rotation&#039;&#039;&#039; around the X axis you might use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
rotation rot30X = llEuler2Rot(&amp;lt;30, 0, 0&amp;gt;*DEG_TO_RAD);           // convert the degrees to radians, then convert that vector into a rotation, rot30x&lt;br /&gt;
vector   vec30X = llRot2Euler(rot30X);                          // convert the rotation back to a vector (the values will be in radians)&lt;br /&gt;
rotation rot30X = llAxisAngle2Rot(&amp;lt;1, 0, 0&amp;gt;, 30.0*DEG_TO_RAD);  // convert the degrees to radians, then convert into a rotation, rot30x&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Differences between math&#039;s quaternions and LSL rotations ==&lt;br /&gt;
&lt;br /&gt;
There are a few differences between LSL and maths that have little consequences while scripting, but that might puzzle people with prior mathematical knowledge. So we thought it would be good to list them here:&lt;br /&gt;
&lt;br /&gt;
* In LSL, all quaternions are normalized (the dot product of &#039;&#039;&#039;R&#039;&#039;&#039; by &#039;&#039;&#039;R&#039;&#039;&#039; is always &#039;&#039;&#039;1&#039;&#039;&#039;), and therefore represent ways to rotate objects without changing their size. In maths, generic quaternions might be not normalized, and they represent &#039;&#039;affinities&#039;&#039;, i.e. a way to rotate &#039;&#039;&#039;and&#039;&#039;&#039; change the size of objects.&lt;br /&gt;
* In LSL, the &#039;&#039;&#039;s&#039;&#039;&#039; term is the fourth member of the rotation: &#039;&#039;&#039;&amp;lt;x, y, z, s&amp;gt;&#039;&#039;&#039;. In maths, the &#039;&#039;&#039;s&#039;&#039;&#039; term, also called &amp;quot;real part&amp;quot;, is written as the first coordinate of the quaternion: &#039;&#039;&#039;(s, x, y, z)&#039;&#039;&#039;.&lt;br /&gt;
* Multiplication is written in reverse order in LSL and in maths. In LSL, you would write &#039;&#039;&#039;R * S&#039;&#039;&#039;, where in maths you would write &#039;&#039;&#039;S . R&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Order of rotation for Euler Vectors ==&lt;br /&gt;
&lt;br /&gt;
From the above discussion, it&#039;s clear that when dealing with rotations around more than one axis, the order they are done in is critical. In the &#039;&#039;Euler&#039;&#039; discussion above this was kind of glossed over a bit, the individual rotations around the three axis define an overall &#039;&#039;rotation&#039;&#039;, but that begs the question: What axis order are the rotations done in? The answer is &#039;&#039;&#039;Z, Y, X&#039;&#039;&#039; in global coordinates. If you are trying to rotate an object around more than one axis at a time using the &#039;&#039;Euler&#039;&#039; representation, determine the correct &#039;&#039;Euler&#039;&#039; {{LSLG|vector}} using the Z, Y, X rotation order, then use the {{LSLG|llEuler2Rot}} function to get the &#039;&#039;&#039;rotation&#039;&#039;&#039; for use in combining rotations or applying the rotation to the object.&lt;br /&gt;
&lt;br /&gt;
== Local vs Global (World) rotations ==&lt;br /&gt;
&lt;br /&gt;
It is important to distinguish between the &#039;&#039;&#039;rotation&#039;&#039;&#039; relative to the world, and the &#039;&#039;&#039;rotation&#039;&#039;&#039; relative to the local object itself.  In the editor, you can switch back and forth from one to the other.  In a script, you must convert from one to the other to get the desired behavior.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Local&#039;&#039;&#039; rotations are ones done around the axes embedded in the object itself forward/back, left/right, up/down, irrespective of how the object is rotated in the world. &#039;&#039;&#039;Global&#039;&#039;&#039; rotations are ones done around the world axes, North/South, East/West, Higher/Lower. You can see the difference by rotating a prim, then edit it and change the axes settings between local and global, notice how the colored axes arrows change.&lt;br /&gt;
&lt;br /&gt;
In LSL, the difference between doing a &#039;&#039;&#039;local&#039;&#039;&#039; or &#039;&#039;&#039;global&#039;&#039;&#039; rotation is the order the &#039;&#039;&#039;rotations&#039;&#039;&#039; are evaluated in the statement.&lt;br /&gt;
&lt;br /&gt;
This does a &#039;&#039;&#039;local&#039;&#039;&#039; 30 degree rotation by putting the constant 30 degree &#039;&#039;&#039;rotation&#039;&#039;&#039; to the left of the object&#039;s starting &#039;&#039;&#039;rotation&#039;&#039;&#039; (myRot). It is like the first operation in the first example above, just twisting the dart 30 degrees around its own long axis. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
rotation localRot = rot30X * myRot;//  do a local rotation by multiplying a constant rotation by a world rotation&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To do a &#039;&#039;&#039;global&#039;&#039;&#039; rotation, use the same &#039;&#039;&#039;rotation&#039;&#039;&#039; values, but in the opposite order. This is like the second operation in the second example, the dart rotating up and to the right around the world X axis. In this case, the existing rotation (myRot) is rotated 30 degrees around the global X axis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
rotation globalRot = myRot * rot30X;// do a global rotation by multiplying a world rotation by a constant rotation&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Another way to think about combining rotations ==&lt;br /&gt;
&lt;br /&gt;
You may want to think about this &#039;&#039;&#039;local&#039;&#039;&#039; vs &#039;&#039;&#039;global&#039;&#039;&#039; difference by considering that &#039;&#039;&#039;rotations&#039;&#039;&#039; are done in evaluation order, that is left to right except for parenthesized expressions.&lt;br /&gt;
&lt;br /&gt;
In the localRot case, what happened was that starting from &amp;lt;0, 0, 0&amp;gt;, the rot30X was done first, rotating the prim around the world X axis, but since when it&#039;s unrotated, the local and global axes are identical it has the effect of doing the rotation around the object&#039;s local X axis. Then the second &#039;&#039;&#039;rotation&#039;&#039;&#039; myRot was done which rotated the prim to its original rotation, but now with the additional X axis rotation baked in. What this looks like is that the prim rotated in place, around its own X axis, with the Y and Z rotations unchanged, a &#039;&#039;&#039;local&#039;&#039;&#039; rotation.&lt;br /&gt;
&lt;br /&gt;
In the globalRot case, again starting from &amp;lt;0, 0, 0&amp;gt;, first the object is rotated to its original rotation (myRot), but now the object&#039;s axes and the world&#039;s axes are no longer aligned! So, the second &#039;&#039;&#039;rotation&#039;&#039;&#039; rot30x does exactly what it did in the local case, rotates the object 30 degrees around the world X axis, but the effect is to rotate the object through a cone around the world X axis since the object&#039;s X axis and the world&#039;s X axis aren&#039;t the same this time. What this looks like is that the prim pivoted 30 degrees around the world X axis, hence a &#039;&#039;&#039;global&#039;&#039;&#039; rotation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; of &#039;&#039;&#039;rotations&#039;&#039;&#039; has the effect of doing the rotation in the opposite direction, multiplying by a 330 degree &#039;&#039;&#039;rotation&#039;&#039;&#039; is the same as dividing by a 30 degree &#039;&#039;&#039;rotation&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Using Rotations ==&lt;br /&gt;
&lt;br /&gt;
You can access the individual components of a &#039;&#039;&#039;rotation&#039;&#039;&#039; &#039;&#039;&#039;R&#039;&#039;&#039; by &#039;&#039;&#039;R.x, R.y, R.z, &amp;amp; R.s&#039;&#039;&#039; (&#039;&#039;&#039;not&#039;&#039;&#039; R.w).  The scalar part R.s is the cosine of half the angle of rotation.  The vector part (R.x,R.y,R.z) is the product of the normalized axis of rotation and the sine of half the angle of rotation.  You can generate an inverse &#039;&#039;&#039;rotation&#039;&#039;&#039; by negating the x,y,z members (or by making the s value negative). As an aside, you can also use a &#039;&#039;&#039;rotation&#039;&#039;&#039; just as a repository of [[float]] values, each &#039;&#039;&#039;rotation&#039;&#039;&#039; stores four of them and a [[list]] consisting of &#039;&#039;&#039;rotation&#039;&#039;&#039; is more efficient than a [[list]] consisting of [[float]]s, but there is overhead in unpacking them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
rotation rot30X      = llEuler2Rot(&amp;lt;30, 0, 0&amp;gt; * DEG_TO_RAD );//  Create a rotation constant&lt;br /&gt;
rotation rotCopy     = rot30X;                               //  Just copy it into rotCopy, it copies all 4 float components&lt;br /&gt;
float    X           = rotCopy.x;                            //  Get out the individual components of the rotation&lt;br /&gt;
float    Y           = rotCopy.y;&lt;br /&gt;
float    Z           = rotCopy.z;&lt;br /&gt;
float    S           = rotCopy.s;&lt;br /&gt;
rotation anotherCopy = &amp;lt;X, Y, Z, S&amp;gt;;                         // = &amp;lt;rotCopy.x, rotCopy.y, rotCopy.y, rotCopy.s&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is a built in constant for a zero &#039;&#039;&#039;rotation&#039;&#039;&#039; [[#ZERO_ROTATION|ZERO_ROTATION]] which you can use directly or, if you need to invert a &#039;&#039;&#039;rotation R&#039;&#039;&#039;, divide [[#ZERO_ROTATION|ZERO_ROTATION]] by &#039;&#039;&#039;R&#039;&#039;&#039;. As a reminder from above, this works by first rotating to the zero position, then because it is a divide, rotating in the opposite sense to the original  &#039;&#039;&#039;rotation&#039;&#039;&#039;, thereby doing the inverse rotation.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
rotation rot330X        = &amp;lt;-rot30X.x, -rot30X.y, -rot30X.z, rot30X.s&amp;gt;;//  invert a rotation - NOTE the s component isn&#039;t negated&lt;br /&gt;
rotation another330X    = ZERO_ROTATION / rot30X;                     //  invert a rotation by division, same result as rot330X&lt;br /&gt;
rotation yetanother330X = &amp;lt;rot30X.x, rot30X.y, rot30X.z, -rot30X.s&amp;gt;;  //  not literally the same but works the same.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Single or Root Prims vs Linked Prims vs Attachments ==&lt;br /&gt;
&lt;br /&gt;
The reason for talking about single or linked prim rotations is that for things like doors on vehicles, the desired motion is to move the door relative to the vehicle, no matter what the rotation of the overall vehicle is. While possible to do this with global rotations, it would quickly grow tedious.&lt;br /&gt;
There are generally three coordinate systems a prim can be in: all alone, part of a {{LSLG|linkset}}, or part of an {{LSLG|attachment}}. When a prim is alone, i.e., not part of a {{LSLG|linkset}}, it acts like a root prim; when it is part of an {{LSLG|attachment}}, it acts differently and is a bit broken.&lt;br /&gt;
&lt;br /&gt;
{{LSLRotGetSet}}&lt;br /&gt;
&lt;br /&gt;
==Rotating Vectors ==&lt;br /&gt;
&lt;br /&gt;
In LSL, rotating a [[vector]] is very useful if you want to move an object in an arc or circle when the center of rotation isn&#039;t the center of the object.&lt;br /&gt;
&lt;br /&gt;
This sounds very complex, but there is much less here than meets the eye. Remember from the above discussion of rotating the [[#Combining Rotations|dart]], and replace the physical dart with a [[vector]] whose origin is the tail of the dart, and whose components in X, Y, and Z describe the position of the tip of the dart. Rotating the dart around its tail moves the tip of the dart through and arc whose center of rotation is the tail of the dart. In exactly the same way, rotating a [[vector]] which represents an offset from the center of a prim rotates the prim through the same arc. What this looks like is the object rotates around a position offset by the [[vector]] from the center of the prim.&lt;br /&gt;
=== Position of Object Rotated Around A Relative Point ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;rotation vRotArc       = llEuler2Rot( &amp;lt;30.0, 0.0, 0.0&amp;gt; * DEG_TO_RAD );&lt;br /&gt;
 //-- creates a rotation constant, 30 degrees around the X axis&lt;br /&gt;
&lt;br /&gt;
vector   vPosOffset     = &amp;lt;0.0, 1.0, 0.0&amp;gt;;&lt;br /&gt;
 //-- creates an offset one meter in the positive Y direction&lt;br /&gt;
&lt;br /&gt;
vector   vPosRotOffset  = vPosOffset * vRotArc;&lt;br /&gt;
 //-- rotates the offset to get the motion caused by the rotation&lt;br /&gt;
&lt;br /&gt;
vector   vPosOffsetDiff = vPosOffset - vPosRotOffset;&lt;br /&gt;
 //-- gets the local difference between the current offset and the rotated one&lt;br /&gt;
&lt;br /&gt;
vector   vPosRotDiff    = vPosOffsetDiff * llGetRot();&lt;br /&gt;
 //-- rotates the difference in the offsets to be relative to the global rotation.&lt;br /&gt;
&lt;br /&gt;
vector   vPosNew        = llGetPos() + vPosRotDiff;&lt;br /&gt;
 //-- finds the prims new position by adding the rotated offset difference&lt;br /&gt;
&lt;br /&gt;
rotation vRotNew        = vRotArc * llGetRot();&lt;br /&gt;
 //-- finds rot to continue facing offset point&amp;lt;/source&amp;gt;&lt;br /&gt;
:in application, the same action as:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (vPosOffset - vPosOffset * vRotArc) * llGetRot(),&lt;br /&gt;
                       PRIM_ROTATION, vRotArc * llGetRot()] );&amp;lt;/source&amp;gt;&lt;br /&gt;
* The above method results in the orbiting object always having the same side facing the center. An alternative that preserves the orbiters rotation is as follows&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (vPosOffset - vPosOffset * vRotArc) * llGetRot()];&lt;br /&gt;
vPosOffset = vPosOffset * vRotArc;&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Nota Bene:&#039;&#039;&#039; Doing this is a move, so don&#039;t forget about issues of moving a prim off world, below ground, more than 10 meters etc. Also to get a full orbit, you&#039;ll need to repeat the listed steps (in a [[timer]] perhaps).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notice:&#039;&#039;&#039; These apply to objects (or root prims if you prefer), child prims should use [[PRIM_POS_LOCAL]] for position, and [[PRIM_ROT_LOCAL]] or [[llGetLocalRot]] for rotation, and the point being rotated around should be relative to the root.&lt;br /&gt;
&lt;br /&gt;
=== Position of Relative Point Around Rotated Object ===&lt;br /&gt;
To get a point relative to the objects current facing (such as used in rezzors)&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;vector   vPosOffset     = &amp;lt;0.0, 0.0, 1.0&amp;gt;;&lt;br /&gt;
 //-- creates an offset one meter in the positive Z direction.&lt;br /&gt;
&lt;br /&gt;
vector   vPosRotOffset  = vPosOffset * llGetRot();&lt;br /&gt;
 //-- rotate the offset to be relative to objects rotation&lt;br /&gt;
&lt;br /&gt;
vector   vPosOffsetIsAt = llGetPos() + vPosRotOffset;&lt;br /&gt;
 //-- get the region position of the rotated offset&amp;lt;/source&amp;gt;&lt;br /&gt;
:in application, the same action as:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;llRezAtRoot( &amp;quot;Object&amp;quot;, llGetPos() + vPosOffset * llGetRot(), ZERO_VECTOR, ZERO_ROTATION, 0 );&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Normalizing a Rotation ==&lt;br /&gt;
When you need precision, it is often important -- even necessary -- to work with normalized rotations, which means scaling each quaternion so that its &#039;&#039;x, y,&#039;&#039; and &#039;&#039;z&#039;&#039; values are equal to 1. Some operations in LSL will actually generate a run-time error if you do not do this. Looking at it another way, you need to express the rotation in a way that applies an angle of rotation to a vector &amp;lt;1.0,1.0,1.0&amp;gt;.  Mathematically, normalizing rotation &#039;&#039;&#039;Q&#039;&#039;&#039; means calculating &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Normalized Q = Q / Sqrt( Q.x^2 + Q.y^2 + Q.z^2 + Q.s^2)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Putting that in LSL terms:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;rotation NormRot(rotation Q)&lt;br /&gt;
{&lt;br /&gt;
    float MagQ = llSqrt(Q.x*Q.x + Q.y*Q.y +Q.z*Q.z + Q.s*Q.s);&lt;br /&gt;
    return &amp;lt;Q.x/MagQ, Q.y/MagQ, Q.z/MagQ, Q.s/MagQ&amp;gt;;&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
: &#039;&#039;&#039;Note&#039;&#039;&#039;: The only methods in LSL for obtaining a de-normalized rotations are [[llAxes2Rot]] (&#039;&#039;via inputs which are not mutually orthogonal, or via inputs of different magnitude&#039;&#039;), or direct manipulation of the rotation&#039;s elements. All other ll* functions return normalized rotations. Use of the preceding example may introduce small floating point errors into normalized rotations due to limited precision.&lt;br /&gt;
&lt;br /&gt;
==Useful Snippets==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;integer IsRotation(string s)&lt;br /&gt;
{&lt;br /&gt;
    list split = llParseString2List(s, [&amp;quot; &amp;quot;], [&amp;quot;&amp;lt;&amp;quot;, &amp;quot;&amp;gt;&amp;quot;, &amp;quot;,&amp;quot;]);&lt;br /&gt;
    if(llGetListLength(split) != 9)//we must check the list length, or the next test won&#039;t work properly.&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    return !((string)((rotation)s) == (string)((rotation)((string)llListInsertList(split, [&amp;quot;-&amp;quot;], 7))));&lt;br /&gt;
    //it works by trying to flip the sign on the S element of the rotation,&lt;br /&gt;
    //if it works or breaks the rotation then the values won&#039;t match.&lt;br /&gt;
    //if the rotation was already broken then the sign flip will have no affect and the values will match&lt;br /&gt;
    //we cast back to string so we can catch negative zero which allows for support of &amp;lt;0,0,0,0&amp;gt;&lt;br /&gt;
}//Strife Onizuka&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{CopyAsComment|Calculate a point at distance d in the direction the avatar id is facing}}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;vector point_in_front_of( key id, float d )&lt;br /&gt;
{&lt;br /&gt;
    list pose = llGetObjectDetails( id, [ OBJECT_POS, OBJECT_ROT ] );&lt;br /&gt;
    return ( llList2Vector( pose, 0 ) + &amp;lt; d, 0.0, 0.0 &amp;gt; * llList2Rot( pose, 1 ) );&lt;br /&gt;
}// Mephistopheles Thalheimer&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{CopyAsComment|Rez an object o at a distance d from the end of the z axis.&amp;lt;br&amp;gt;&lt;br /&gt;
The object is rezzed oriented to the rezzer}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;rez_object_at_end( string o, float d )&lt;br /&gt;
{&lt;br /&gt;
    vector s = llGetScale();&lt;br /&gt;
    &lt;br /&gt;
    if( llGetInventoryType( o ) == INVENTORY_OBJECT )&lt;br /&gt;
    {&lt;br /&gt;
        llRezObject( o, llGetPos() + llRot2Up( llGetRot() ) * ( s.z / 2.0 + d ) , ZERO_VECTOR, llGetRot(), 0 );&lt;br /&gt;
    }&lt;br /&gt;
}// Mephistopheles Thalheimer&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CopyAsComment|Scale a rotation:}}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;rotation ScaleQuat(rotation source, float ratio)&lt;br /&gt;
{&lt;br /&gt;
	return llAxisAngle2Rot(llRot2Axis(source), ratio * llRot2Angle(source));&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CopyAsComment|Constrain a rotation to a given plane, defined by its normal, very useful for vehicles that remain horizontal in turns:&amp;lt;br/&amp;gt;&lt;br /&gt;
Note that there is a flaw somewhere in this function, it gives incorrect results in some circumstances.}}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;rotation ConstrainQuat2Plane(rotation source, vector normal)&lt;br /&gt;
{&lt;br /&gt;
	return llAxisAngle2Rot(normal, &amp;lt;source.x, source.y, source.z&amp;gt; * normal * llRot2Angle(source));&lt;br /&gt;
} // Jesrad Seraph&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CopyAsComment|Slerp (rotation combination) function from [[Slerp]]:}}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;rotation BlendQuats(rotation a, rotation b, float ratio)&lt;br /&gt;
{&lt;br /&gt;
	return llAxisAngle2Rot(llRot2Axis(b /= a), ratio * llRot2Angle(b)) * a;&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Constants ==&lt;br /&gt;
=== [[ZERO_ROTATION]] ===&lt;br /&gt;
ZERO_ROTATION = &amp;lt;0.0, 0.0, 0.0, 1.0&amp;gt;;&amp;lt;br/&amp;gt;&lt;br /&gt;
A rotation constant representing a Euler angle of &amp;lt;0.0, 0.0, 0.0&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== [[DEG_TO_RAD]] ===&lt;br /&gt;
DEG_TO_RAD = 0.01745329238f;&amp;lt;br/&amp;gt;&lt;br /&gt;
A float constant that when multiplied by an angle in degrees gives the angle in radians.&lt;br /&gt;
&lt;br /&gt;
=== [[RAD_TO_DEG]] ===&lt;br /&gt;
RAD_TO_DEG = 57.29578f;&amp;lt;br/&amp;gt;&lt;br /&gt;
A float constant when multiplied by an angle in radians gives the angle in degrees.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LSL_Types|Rotation]][[Category:LSL_Math]][[Category:LSL_Math/3D]][[Category:LSL Rotation]]&lt;/div&gt;</summary>
		<author><name>Fenchurch Oh</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Template:LSL_Function/negative_index/range&amp;diff=1209808</id>
		<title>Template:LSL Function/negative index/range</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Template:LSL_Function/negative_index/range&amp;diff=1209808"/>
		<updated>2020-12-28T18:37:03Z</updated>

		<summary type="html">&lt;p&gt;Fenchurch Oh: typo correction. &amp;quot;Then&amp;quot; vs &amp;quot;Than&amp;quot;.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:&lt;br /&gt;
&lt;br /&gt;
TODO:  --FIXME--&lt;br /&gt;
* Figure out how to support {{{noExclude|}}} for llListListStride.&lt;br /&gt;
&lt;br /&gt;
{{#vardefine:p_{{{1|start}}}_desc|{{{1|start}}} index}}&lt;br /&gt;
&lt;br /&gt;
{{#vardefine:p_{{{2|end}}}_desc|{{{2|end}}} index}}&lt;br /&gt;
&lt;br /&gt;
{{#vardefine:notes|{{#var:notes}}{{PBR}}&lt;br /&gt;
=== Ranges &amp;amp; Indexes ===&lt;br /&gt;
The easiest way to explain how ranges work is to make all indexes positive. Negative indexes are just a way of counting from the tail end instead of the beginning, all negative indexes have a corresponding equivalent positive index (assuming they are in range). Positive indexes past length (after the last index), or negative indexes past the beginning (before the first index) are valid and the effects are predictable and reliable: the entries are treated as if they were there but were removed just before output.&lt;br /&gt;
&lt;br /&gt;
*If {{LSLP|{{{1}}}}} &amp;lt;= {{LSLP|{{{2}}}}} then the range operated on starts at {{LSLP|{{{1}}}}} and ends at {{LSLP|{{{2}}}}}. [{{LSLP|{{{1}}}}}, {{LSLP|{{{2}}}}}]&lt;br /&gt;
*&amp;lt;span id=&amp;quot;exclusion_range&amp;quot;&amp;gt;Exclusion range&amp;lt;/span&amp;gt;: If {{LSLP|{{{1}}}}} &amp;gt; {{LSLP|{{{2}}}}} then the range operated on starts at {{LSLP|0}} and goes to {{LSLP|{{{2}}}}} and then starts again at {{LSLP|{{{1}}}}} and goes to {{LSLP|-1}}. [{{LSLP|0}}, {{LSLP|{{{2}}}}}] + [{{LSLP|{{{1}}}}}, {{LSLP|-1}}]&lt;br /&gt;
**If {{LSLP|{{{2}}}}} is a negative index past the beginning, then the operating range would be [{{LSLP|{{{1}}}}}, {{LSLP|-1}}].&lt;br /&gt;
**If {{LSLP|{{{2}}}}} is a positive index past the end, then the operating range would be [{{LSLP|0}}, {{LSLP|{{{2}}}}}].&lt;br /&gt;
**If both {{LSLP|{{{1}}}}} and {{LSLP|{{{2}}}}} are out of bounds then the function would have no operating range (effectively inverting what the function is supposed to do).&lt;br /&gt;
&lt;br /&gt;
See {{LSLGC|Negative_Index#Range Functions|negative indexes}} for more information.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{| {{Prettytable}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
! #var&lt;br /&gt;
! value&lt;br /&gt;
|-&lt;br /&gt;
{{VarPair|p_{{{1|start}}}_desc}}&lt;br /&gt;
|-&lt;br /&gt;
{{VarPair|p_{{{1|end}}}_desc}}&lt;br /&gt;
|-&lt;br /&gt;
{{VarPair|spec}}&lt;br /&gt;
|-&lt;br /&gt;
{{VarPair|notes}}&lt;br /&gt;
|-&lt;br /&gt;
{{VarPair|caveats}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fenchurch Oh</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Project:Editing_Guidelines&amp;diff=1209760</id>
		<title>Project:Editing Guidelines</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Project:Editing_Guidelines&amp;diff=1209760"/>
		<updated>2020-12-15T23:16:41Z</updated>

		<summary type="html">&lt;p&gt;Fenchurch Oh: /* How can I contribute? */  - updated to current procedure how to request wiki edit permissions. (Dec 2020)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Help|Wiki=*}} {{TOCright}}&lt;br /&gt;
&lt;br /&gt;
== Why should I contribute to the Wiki? ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Just like Second Life itself, this wiki is powered by user generated content&#039;&#039;&#039;, whether it&#039;s a brief tip you want to share or an extensive how-to guide on a given topic. Plus, it&#039;s convenient for your own reference. Many valuable contributions are exactly that: you solved a problem for yourself, which in turn benefits fellow Residents.&lt;br /&gt;
&lt;br /&gt;
Not a techy geek? Don&#039;t worry, &#039;&#039;&#039;Residents from all walks of &amp;quot;Second Life&amp;quot;&#039;&#039;&#039; contribute here, and having diverse perspectives on a single help page can truly be more than the &amp;quot;sum of its parts&amp;quot;. &#039;&#039;&#039;Need reassurance? See [[wiki myths busted]].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Just like you didn&#039;t go from being a baby to a grownup in a day, knowledge on this wiki evolves gradually. There&#039;s no rush. Enjoy checking back and becoming more comfortable over time, learning from others&#039; contributions so you become more confident to make your own.&lt;br /&gt;
&lt;br /&gt;
== How can I contribute? ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Every Resident can create new pages and add to many existing pages.&#039;&#039;&#039; There&#039;s no obligation to, but Linden lab welcomes &#039;&#039;your&#039;&#039; awesome contributions! Before you edit, we recommend being familiar with browsing this wiki, so you understand [[Style_Guide|style]], structure, and content. While there are similarities to other wikis out there, certain specifics apply here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2019:&#039;&#039;&#039; &#039;&#039;For some time who can create in and edit the wiki has been limited due to general abuse of the privileges. You might build cred attending [https://wiki.secondlife.com/wiki/Linden_Lab_Official:User_Groups user group meetings]. If you log into the wiki and see you do not have edit privileges, you&#039;ll need to request them by emailing letmein@lindenlab.com. Please send them a polite email asking for editing permission.&lt;br /&gt;
&#039;&#039;&lt;br /&gt;
=== Editing pages ===&lt;br /&gt;
&lt;br /&gt;
Editing an existing page is super-easy. You may want to start by correcting a typo or other small change:&lt;br /&gt;
&lt;br /&gt;
# Click &#039;&#039;&#039;Log in&#039;&#039;&#039; in the upper right.&lt;br /&gt;
# Enter your Second Life username and password.&lt;br /&gt;
# Click &#039;&#039;&#039;Log in&#039;&#039;&#039;.&lt;br /&gt;
# Go to the page you want to edit.&lt;br /&gt;
# Click the &#039;&#039;&#039;edit&#039;&#039;&#039; tab near the top.&lt;br /&gt;
# Make changes, then scroll to the bottom and click &#039;&#039;&#039;Show preview&#039;&#039;&#039;.&lt;br /&gt;
# If happy with your changes, scroll to the bottom and click &#039;&#039;&#039;Save page&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This video shows you how to do it in action:&lt;br /&gt;
&lt;br /&gt;
: {{KBvideo|VJFGUv5KnG8|640|385|type=youtube}}&lt;br /&gt;
&lt;br /&gt;
{{KBtip|If you&#039;d like to see a help page edited/created but aren&#039;t confident enough to do it yourself and don&#039;t know a more experienced friend who could help, feel free to [http://bit.ly/contactsl ask Torley Linden].}}&lt;br /&gt;
&lt;br /&gt;
=== Creating pages ===&lt;br /&gt;
&lt;br /&gt;
To create a new page which can be edited by you and others, &#039;&#039;&#039;[[Quickie Wiki Intro|read the &amp;quot;Quickie Wiki Intro&amp;quot;]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When creating a new page:&lt;br /&gt;
&lt;br /&gt;
* Help prevent wiki sprawl by editing existing pages rather than creating new pages when possible.&lt;br /&gt;
* Use the simplest, most obvious name. You can always create a redirect and/or disambiguation page later if needed.&lt;br /&gt;
* When a page is aimed at a specific audience, please include a brief introduction for people who aren&#039;t familiar  with the content, or link to further information.&lt;br /&gt;
&lt;br /&gt;
=== [[#&amp;quot;User&amp;quot; namespace|What&#039;s a &amp;quot;User&amp;quot; page?]] ===&lt;br /&gt;
&lt;br /&gt;
^ Click to learn more.&lt;br /&gt;
&lt;br /&gt;
=== See also ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;[[Style Guide]]&#039;&#039;&#039; - Essential reading if you&#039;re planning to edit the &#039;&#039;&#039;[[Extended Knowledge Base]]&#039;&#039;&#039;, but highly recommended in general.&lt;br /&gt;
* &#039;&#039;[http://www.mediawiki.org/wiki/Help:Contents MediaWiki&#039;s Help]&#039;&#039;&#039; - wiki.secondlife.com is powered by MediaWiki, and while we don&#039;t use &#039;&#039;all&#039;&#039; the stuff here, a great deal does apply. There are many techniques that have been ported over here.&lt;br /&gt;
&lt;br /&gt;
== Content ==&lt;br /&gt;
&lt;br /&gt;
We appreciate any info that benefits our Second Life community. This &#039;&#039;excludes&#039;&#039; blatant ads and spam. All content must be [[Maturity#General|suitable for general consumption]] ({{Mrg}} in terms of inworld ratings), and compliant with our [[LL:Second Life Community Standards|Community Standards]] as well as the [[LL:Second Life Terms of Service|Terms of Service]]. While the wiki is a different tool than the blogs and forums, [https://blogs.secondlife.com/community/features/blog/2009/02/25/second-life-discussion-guidelines their discussion guidelines] are also relevant here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;All content added to the Second Life Wiki &#039;&#039;must&#039;&#039; be compatible with our [[Project:Terms of Use|Terms of Use]] and [[Project:Contribution Agreement|Contribution Agreement]].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Besides that, [http://en.wikipedia.org/wiki/Wikipedia:Be_bold &#039;&#039;&#039;be bold&#039;&#039;&#039;].&lt;br /&gt;
&lt;br /&gt;
=== Point of View ===&lt;br /&gt;
&lt;br /&gt;
Articles should generally be written in the [http://en.wikipedia.org/wiki/Third-person_narrative#Third-person_view third person] unless there&#039;s an exceptional benefit, commonly the attribution and accountability that comes with sharing personal experiences. Always consider context: for example, a legal document from Linden Lab must be presented in much more formal language than a subjective guide to creating art.&lt;br /&gt;
&lt;br /&gt;
Second Life has a unique [[culture]], so while we&#039;ve been inspired by others&#039; practices, this wiki&#039;s ultimate authority is Linden Lab, not rules made elsewhere. Specific moderation is done at the discretion of [[Project:About|these Lindens]]. Note that while [http://en.wikipedia.org/wiki/Wikipedia:Neutral_point_of_view Wikipedia&#039;s NPOV] can be a useful guideline, we don&#039;t strictly enforce it, and when it comes to comprehension, are more generous to include information, akin to [http://tvtropes.org/pmwiki/pmwiki.php/Main/HomePage TVTropes].&lt;br /&gt;
&lt;br /&gt;
This wiki is for people helping build Second Life, &#039;&#039;not&#039;&#039; for complaints about Second Life or Linden Lab. Criticism which supports a feature requests or proposal is acceptable (e.g., &amp;quot;Here&#039;s problem X. Implementing Y will solve X.&amp;quot;), but refrain from un-useful complaints. A page history&#039;s contains its complete list of contributions, so there&#039;s no need to sign articles — conversation should go in a page&#039;s accompanying Talk page (accessed by clicking the Discussion tab near the top of the screen).&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;Edits by proxy&amp;quot; aren&#039;t allowed ===&lt;br /&gt;
&lt;br /&gt;
Making edits on another Resident&#039;s behalf isn&#039;t allowed because it confuses accountability and is prone to [http://en.wikipedia.org/wiki/Drama_triangle drama] which wastes everyone&#039;s time. Furthermore, your wiki editing privileges could be revoked. For example, Bob can&#039;t add a paragraph to an article and claim that Alice made him do that. This becomes especially troublesome if the edit is abusive. Rather, the correct path of action is for Alice to edit the page herself as best as she can, then Bob makes further edits. It only takes a few clicks for even a new Resident to begin editing the wiki [http://www.youtube.com/watch?v=VJFGUv5KnG8 as shown in this video], and while you can certainly seek help, &#039;&#039;&#039;you are responsible for all wiki edits made under your Second Life account name&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This relates to [http://secondlife.com/corporate/tos.php#tos3 3.2 in the Second Life Terms of Service]:&lt;br /&gt;
&lt;br /&gt;
: 3.2 You agree to use an Account Name in Second Life that is not misleading, offensive or infringing. You are responsible for activities related to your Account Name, and for keeping your password for this Account secure.&lt;br /&gt;
&lt;br /&gt;
=== Localization ===&lt;br /&gt;
&lt;br /&gt;
See [[Project:Languages]] for localization guidelines. &lt;br /&gt;
&lt;br /&gt;
=== Removal of content ===&lt;br /&gt;
&lt;br /&gt;
[[Resident|Residents]] can&#039;t permanently remove content from the wiki. Use redirects for merged or accidentally-created pages. Articles can be tagged with [[Template:Delete]] where redirects seem inappropriate (e.g., where the wiki is used in an abusive manner or where it violates copyright).&lt;br /&gt;
&lt;br /&gt;
=== Linking of content ===&lt;br /&gt;
&lt;br /&gt;
Please link pages to related resources to facilitate learning. Link the first appearance in text of a term in need of explanation (like [[avatar]], [[grid]], [[OGP]], etc.).&lt;br /&gt;
&lt;br /&gt;
Categorize your pages where appropriate. [http://wiki.secondlife.com/wiki/Special:AllPages?namespace=14 See the full list of available categories.]&lt;br /&gt;
&lt;br /&gt;
It&#039;s also awesome to have a &amp;quot;See also&amp;quot; section at the end of an article linking to related articles that the reader may wish to learn from next. [[Marketplace/Sellers_guide#See_also|See an example.]]&lt;br /&gt;
&lt;br /&gt;
If a single article feels &amp;quot;too long&amp;quot;, dividing it into smaller, focused articles and linking them is often the more accessible way to go. Articles are expected to evolve fluidly, so there&#039;s so single rule here — use your best judgment and keep learning by doing.&lt;br /&gt;
&lt;br /&gt;
== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
Geeky but good-to-know.&lt;br /&gt;
&lt;br /&gt;
=== Main ===&lt;br /&gt;
&lt;br /&gt;
The Main [http://www.mediawiki.org/wiki/Namespaces namespace] is intended to hold most of the Second Life Wiki&#039;s content.&lt;br /&gt;
&lt;br /&gt;
=== Linden Lab Official ===&lt;br /&gt;
&lt;br /&gt;
The [http://wiki.secondlife.com/w/index.php?title=Special%3AAllPages&amp;amp;from=&amp;amp;to=&amp;amp;namespace=100 Linden Lab Official namespace] is for official Second Life policy information and other information from Linden Lab, such as official supported API documentation, safety and security guidelines, and information related to billing and payments.  Only Linden Lab employees may edit these articles, though the talk namespace is open for general editing.&lt;br /&gt;
&lt;br /&gt;
There are also localized official namespaces:&lt;br /&gt;
* French - [http://wiki.secondlife.com/w/index.php?title=Special%3AAllPages&amp;amp;from=&amp;amp;to=&amp;amp;namespace=104 Article officiel de Linden Lab]&lt;br /&gt;
* Japanese - [http://wiki.secondlife.com/w/index.php?title=Special%3AAllPages&amp;amp;from=&amp;amp;to=&amp;amp;namespace=106 Linden Lab公認]&lt;br /&gt;
* Italian - [http://wiki.secondlife.com/w/index.php?title=Special%3AAllPages&amp;amp;from=&amp;amp;to=&amp;amp;namespace=108 Articolo ufficiale Linden Lab]&lt;br /&gt;
* Portuguese - [http://wiki.secondlife.com/w/index.php?title=Special%3AAllPages&amp;amp;from=&amp;amp;to=&amp;amp;namespace=110 Artigo oficial da Linden Lab]&lt;br /&gt;
* Spanish - [http://wiki.secondlife.com/w/index.php?title=Special%3AAllPages&amp;amp;from=&amp;amp;to=&amp;amp;namespace=112 Artículo oficial de Linden Lab]&lt;br /&gt;
* German - [http://wiki.secondlife.com/w/index.php?title=Special%3AAllPages&amp;amp;from=&amp;amp;to=&amp;amp;namespace=114 Linden Lab Offiziell]&lt;br /&gt;
&lt;br /&gt;
=== Viewer Help ===&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.secondlife.com/w/index.php?title=Special%3AAllPages&amp;amp;from=&amp;amp;to=&amp;amp;namespace=102 Viewerhelp namespace] contains content provided via the Viewer 2 Online Help system.  Only Linden Lab employees may edit these articles, though the talk namespace is open for general editing.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;Project&amp;quot; namespace === &lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Project&amp;quot; namespace is reserved for meta-information about the wiki itself, such as these editing guidelines, rather than about Second Life.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;Help&amp;quot; namespace ===&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Help:&amp;quot; namespace is reserved for wiki-related help articles, like editing manuals. SL-related help should be added to the Main namespace. &lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;User&amp;quot; namespace ===&lt;br /&gt;
&lt;br /&gt;
Every wiki contributor has their own, personal namespace.&lt;br /&gt;
&lt;br /&gt;
Once you login, you can also view and edit your User: page by clicking your name towards the top right (to the left of the &amp;quot;my talk&amp;quot;) link. For example, [[User:Torley_Linden]] and [[User:Zai Lynch]].&lt;br /&gt;
&lt;br /&gt;
Think of it as an extended profile compared to the one inworld. What can you do with it? Just about anything you wish, from expressing who you are to others, to tracking links to wiki pages you regularly edit for your own reference. Customizing your User: page is totally optional, but as you grow on the wiki, helps others understand who you are.&lt;br /&gt;
&lt;br /&gt;
Obviously, the [[#Point of View|Point of View guideline]] doesn&#039;t need to be followed here.&lt;br /&gt;
&lt;br /&gt;
Any content abiding by the wiki guidelines can be included in the &amp;quot;User&amp;quot; namespace as a subpage. For example, [[User:Torley Linden/Contact]].&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;Talk&amp;quot; namespace ===&lt;br /&gt;
&lt;br /&gt;
See [[Project:Talk Page Guidelines]] for more info.&lt;br /&gt;
&lt;br /&gt;
== Templates ==&lt;br /&gt;
&lt;br /&gt;
* Use inclusion templates to ensure consistent navigation.&lt;br /&gt;
* See [[Help:Editors Toolbox]] for a list of useful templates for editors.&lt;br /&gt;
* See [http://wiki.secondlife.com/w/index.php?title=Special%3AAllPages&amp;amp;from=&amp;amp;namespace=10 the list of all available templates].&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;[[Project:Terms of Use]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Project:Contribution Agreement]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Template:Ediquette]]&#039;&#039;&#039; - Editing etiquette&lt;br /&gt;
* &#039;&#039;&#039;[[Project:Talk Page Guidelines]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Project:Languages]]&#039;&#039;&#039; - Guidelines on localizing wiki pages&lt;br /&gt;
* &#039;&#039;&#039;[[:Category:Help/Wiki]]&#039;&#039;&#039; - All wiki-related articles&lt;br /&gt;
* &#039;&#039;&#039;[[Wiki myths busted]]&#039;&#039;&#039; - Fear is the mind-killer!&lt;/div&gt;</summary>
		<author><name>Fenchurch Oh</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Template:LSL_Function/group&amp;diff=1209759</id>
		<title>Template:LSL Function/group</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Template:LSL_Function/group&amp;diff=1209759"/>
		<updated>2020-12-15T22:35:25Z</updated>

		<summary type="html">&lt;p&gt;Fenchurch Oh: typo correction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Injection Test}}{{#if:&lt;br /&gt;
&lt;br /&gt;
{{Issues/VWR-5044}}&lt;br /&gt;
&lt;br /&gt;
{{#vardefine:notes|{{#var:notes}}{{PBR}}&lt;br /&gt;
==== Child Prims ====&lt;br /&gt;
It is possible for the group of a child prim to differ from that of the root prim. To build such an object it must first be unlinked, the groups set, and then relinked. Rezzing an object resets the group of the object to that of the group that the user currently has activated. Changing the group of an object changes the group for the entire object. This may only be an artifact or manifestation of [[#VWR-5044|VWR-5044]].}}&lt;br /&gt;
&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;{{#vardefine:notes}}&lt;br /&gt;
{| {{Prettytable}}&lt;br /&gt;
|+&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{{{FULLPAGENAMEE}}|}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;{{{{FULLPAGENAMEE}}|}}&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
! #var&lt;br /&gt;
! value&lt;br /&gt;
|-&lt;br /&gt;
{{VarPair|notes}}&lt;br /&gt;
|-&lt;br /&gt;
{{VarPairTable|issues}}&lt;br /&gt;
|-&lt;br /&gt;
{{VarPair|BugCounter}}&lt;br /&gt;
|-&lt;br /&gt;
{{VarPair|IssueCounter}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fenchurch Oh</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlEmail&amp;diff=1209758</id>
		<title>LlEmail</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlEmail&amp;diff=1209758"/>
		<updated>2020-12-15T21:40:54Z</updated>

		<summary type="html">&lt;p&gt;Fenchurch Oh: Updated relevant issues list; Added note about potential workaround to prevent email queue from gettung stuck.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|inject-2={{Issues/SVC-23}}{{Issues/SVC-391}}{{Issues/SVC-412}}{{Issues/SCR-499}}{{Issues/BUG-229767}}&lt;br /&gt;
|func_id=119|func_sleep=20.0|func_energy=10.0&lt;br /&gt;
|sort=Email|func=llEmail&lt;br /&gt;
|p1_type=string|p1_name=address&lt;br /&gt;
|p2_type=string|p2_name=subject&lt;br /&gt;
|p3_type=string|p3_name=message&lt;br /&gt;
|func_footnote=The entire message (including the address, subject and other miscellaneous fields) can&#039;t be longer than 4096 bytes combined.&lt;br /&gt;
|func_desc=Sends an email to {{LSLP|address}} with {{LSLP|subject}} and {{LSLP|message}}.&lt;br /&gt;
|return_text&lt;br /&gt;
|spec=The {{LSLP|message}} is prefixed with information about the prim sending the email.&lt;br /&gt;
{{{!}}{{Prettytable}}&lt;br /&gt;
{{!}}-{{Hl2}}&lt;br /&gt;
!Template&lt;br /&gt;
!Example&lt;br /&gt;
{{!}}-&lt;br /&gt;
{{!}}&amp;lt;pre&amp;gt;&lt;br /&gt;
Object-Name: *prim*&lt;br /&gt;
Region: *simname* (*simpos.x*, *simpos.y*)&lt;br /&gt;
Local-Position: (*primpos.x*, *primpos.y*, *primpos.z*)&lt;br /&gt;
&lt;br /&gt;
*message*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
{{!}}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Object-Name: Object&lt;br /&gt;
Region: Gibson (254976, 256000)&lt;br /&gt;
Local-Position: (117, 129, 50)&lt;br /&gt;
&lt;br /&gt;
The real message starts here.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
{{!}}}&lt;br /&gt;
|caveats=* If you&#039;re sending to the object owner, prefer the [[llTargetedEmail]] method&lt;br /&gt;
* There is a limit to the number of email messages an object can send in a given amount of time. &lt;br /&gt;
* There is a limit of 500 messages from a single agent&#039;s objects in a one hour period.&lt;br /&gt;
* The 4096 byte size limit includes the subject line and automatically added text.  The practical maximum body size is approximately 3600 bytes.&lt;br /&gt;
* (Sept-2008) The Email Throttle was modified slightly, Per {{User|Prospero Linden}}&#039;s comments: &amp;quot;there has long been a throttle that makes a single script sleep for 20 seconds after sending an email. The new throttle is per user... some were using many, many different scripts to send spam. (the new throttle applies) when the destination is outside of Second Life. I know that messages within the same region were not throttled (beyond the 20-second delay), and I *believe* that messages between different sims were not throttled (between the 20-second delay).&amp;quot;&lt;br /&gt;
* Due to the bug {{Jira|SVC-23}} (present since 2005), objects may stop receiving emails completely until either the region is restarted or the object crosses a region boundary (resetting the script doesn&#039;t help).  Emails sent may eventually be received after a restart/region-cross.  Hence, don&#039;t rely on this function for reliable inter-region messaging.&lt;br /&gt;
* Due to bug {{JIRA|BUG-229767}}, an object&#039;s email queue can still become suspended until the object crosses a region border (neither a region restart nor a script reset helps). First analysis has revealed a potential workaround, by implementing a delay of about 30 seconds before first trying to send email to a freshly rezzed script - apparently registering the email(...) event handler can take quite some time, and emails arriving prior to said registry process is what gets the entire queue stuck. Official Linden response still pending.&lt;br /&gt;
* Due to the bug {{Jira|SVC-391}} llEmail will silently fail (no mail will arrive) when non-ascii characters are present in the subject. However, non-ascii characters in the message body will be replaced by &amp;quot;?&amp;quot;.&lt;br /&gt;
|constants&lt;br /&gt;
|examples=&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
string emailAddress = &amp;quot;somebody@example.com&amp;quot;;&lt;br /&gt;
string emailHeader = &amp;quot;Someone touched me!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    touch_start(integer num_detected)&lt;br /&gt;
    {&lt;br /&gt;
        // llSay(PUBLIC_CHANNEL, &amp;quot;Sending eMail report now, this will take ~20 seconds.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        key id = llDetectedKey(0);&lt;br /&gt;
        string name = llDetectedName(0);&lt;br /&gt;
&lt;br /&gt;
        llEmail(emailAddress, emailHeader,&lt;br /&gt;
            &amp;quot;I was touched by: &#039;&amp;quot; + name + &amp;quot;&#039; (&amp;quot; + (string)id + &amp;quot;).&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // llSay(PUBLIC_CHANNEL, &amp;quot;Email has been sent.&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|also_functions=&lt;br /&gt;
{{LSL DefineRow||[[llGetNextEmail]]}}&lt;br /&gt;
{{LSL DefineRow||[[llMessageLinked]]}}&lt;br /&gt;
|also_events=&lt;br /&gt;
{{LSL DefineRow||[[email]]}}&lt;br /&gt;
{{LSL DefineRow||[[link message]]}}&lt;br /&gt;
|also_tests={{LSL DefineRow|[https://osiris.lindenlab.com/mediawiki/index.php/Email_Test internal test]}}&lt;br /&gt;
|also_articles={{LSL DefineRow||[[IM to email]]}}&lt;br /&gt;
{{LSL DefineRow||[[Postcards]]}}&lt;br /&gt;
|notes=* Because of the long delay on this function, it is often called from a second script triggered by [[link_message]].&lt;br /&gt;
* If you are sending email to a prim within Second Life, its address is &#039;&#039;[key]&#039;&#039;@lsl.secondlife.com&lt;br /&gt;
** Which means if the key returned by [[llGetKey]] is &amp;quot;a2e76fcd-9360-4f6d-a924-000000000003&amp;quot;, then its email address is &amp;quot;a2e76fcd-9360-4f6d-a924-000000000003@lsl.secondlife.com&amp;quot;.&lt;br /&gt;
** Agents do not have fixed email addresses, use [[llInstantMessage]] or [[llOwnerSay]].&lt;br /&gt;
&lt;br /&gt;
===Prim2Prim Email===&lt;br /&gt;
&lt;br /&gt;
In LSL you can both send email with llEmail and receive it with the [[email]] event.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The email event is triggered with 5 pieces of information.&lt;br /&gt;
{{{!}}&lt;br /&gt;
{{LSL DefineRow|string|time|When the message was sent, in the &amp;lt;code&amp;gt;(string)[[llGetUnixTime]]&amp;lt;/code&amp;gt; format}}&lt;br /&gt;
{{LSL DefineRow|string|address|Who sent the message}}&lt;br /&gt;
{{LSL DefineRow|string|subject|Subject of the message}}&lt;br /&gt;
{{LSL DefineRow|string|message|Body of the message}}&lt;br /&gt;
{{LSL DefineRow|integer|num_left|The number of emails left in the email queue}}&lt;br /&gt;
{{!}}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When receiving a message sent with [[llEmail]] it helps to separate the message from the prefixed header. The header and original message body are separated by &amp;quot;\n\n&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;integer divide = llSubStringIndex(message, &amp;quot;\n\n&amp;quot;);&lt;br /&gt;
string header = llDeleteSubString(message, divide, -1);&lt;br /&gt;
message = llDeleteSubString(message, 0, divide + 1);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get just 1 of the header items, do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;list lines = llParseStringKeepNulls(header, [&amp;quot;\n&amp;quot;], []);&lt;br /&gt;
string objname_line = llList2String(lines, 0);&lt;br /&gt;
string region_line = llList2String(lines, 1);&lt;br /&gt;
string localpos_line = llList2String(lines, 2);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get a pure region name, do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;string region_name = llStringTrim(&lt;br /&gt;
            (string)llDeleteSubList(&lt;br /&gt;
                llParseStringKeepNulls(&lt;br /&gt;
                    llDeleteSubString(region_line, 0, 12),&lt;br /&gt;
                    [], &lt;br /&gt;
                    [&amp;quot;(&amp;quot;]&lt;br /&gt;
                ), -2, -1), STRING_TRIM);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This application uses email to have objects check with a central server to see if the owner has the latest version. In the objects:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;string version = &amp;quot;1&amp;quot;; //&lt;br /&gt;
string type = &amp;quot;lolcube&amp;quot;;&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    on_rez(integer start_param)&lt;br /&gt;
    {&lt;br /&gt;
        llEmail(&amp;quot;5a634b27-f032-283f-2df2-55ead7724b23@lsl.secondlife.com&amp;quot;,&lt;br /&gt;
            version,&lt;br /&gt;
            (string)llGetOwner() + &amp;quot;,&amp;quot; + type);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
The server:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetTimerEvent(15.0);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    timer()&lt;br /&gt;
    {&lt;br /&gt;
        llGetNextEmail(&amp;quot;&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    email( string time, string address, string version, string message, integer num_left )&lt;br /&gt;
    {    &lt;br /&gt;
        if ((integer)version &amp;lt; 2)&lt;br /&gt;
        {&lt;br /&gt;
            list info = llCSV2List( llDeleteSubString(message, 0, llSubStringIndex(message, &amp;quot;\n\n&amp;quot;) + 1));&lt;br /&gt;
            llGiveInventory(llList2Key(info,0), llList2String(info,1));&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if(num_left)&lt;br /&gt;
            llGetNextEmail(&amp;quot;&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
|helpers=&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
email( string time, string address, string subj, string message, integer num_left )&lt;br /&gt;
{&lt;br /&gt;
    if(llGetSubString(address, -19, -1) == &amp;quot;@lsl.secondlife.com&amp;quot;)//trim the header&lt;br /&gt;
        message = llDeleteSubString(message, 0, llSubStringIndex(message, &amp;quot;\n\n&amp;quot;) + 1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|permission&lt;br /&gt;
|negative_index&lt;br /&gt;
|cat1=Communications&lt;br /&gt;
|cat2=Email&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Fenchurch Oh</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Email&amp;diff=1209757</id>
		<title>Email</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Email&amp;diff=1209757"/>
		<updated>2020-12-15T21:38:45Z</updated>

		<summary type="html">&lt;p&gt;Fenchurch Oh: Updated relevant issues list; Added note about potential workaround to prevent email queue from gettung stuck.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Event&lt;br /&gt;
|inject-2={{Issues/SVC-23}}{{Issues/SVC-391}}{{Issues/SVC-412}}{{Issues/SCR-499}}{{Issues/BUG-229767}}&lt;br /&gt;
|event_id=21|event_delay&lt;br /&gt;
|event=email&lt;br /&gt;
|p1_type=string|p1_name=time|p1_desc=In the &amp;lt;code&amp;gt;(string)[[llGetUnixTime]]&amp;lt;/code&amp;gt; format|p1_hover=In the (string)llGetUnixTime format&lt;br /&gt;
|p2_type=string|p2_name=address|p2_desc&lt;br /&gt;
|p3_type=string|p3_name=subject|p3_desc&lt;br /&gt;
|p4_type=string|p4_name=message|p4_desc&lt;br /&gt;
|p5_type=integer|p5_name=num_left|p5_desc=The number of emails remaining in the email queue.{{Footnote|The email being processed is not counted as it has already been popped from the queue.}}|p5_hover=The number of emails left in the email queue.&lt;br /&gt;
|event_desc=Triggered as a result of calling [[llGetNextEmail]] where there is a matching email in the email queue.&lt;br /&gt;
|event_footnote=The email queue is associated with the prim and any script in the prim can access it. &amp;lt;br/&amp;gt; The prim&#039;s email address is its key with &amp;quot;@lsl.secondlife.com&amp;quot; appended, &amp;lt;code&amp;gt;[[llGetKey]]() + &amp;quot;@lsl.secondlife.com&amp;quot;&amp;lt;/code&amp;gt;{{Footnote|1=Preview grid email address are constructed differently: &amp;lt;code style=&amp;quot;font-size: 123%;&amp;quot;&amp;gt;[[llGetKey]]() + &amp;quot;@lsl.&amp;quot; + grid + &amp;quot;.lindenlab.com&amp;quot;&amp;lt;/code&amp;gt;; for the main beta grid set grid to {{String|aditi}}.|2=Beta grid email address are constructed differently: llGetKey() + {{String|@lsl.}} + grid + {{String|.lindenlab.com}}; for the main beta grid set grid to {{String|aditi}}.}}.&lt;br /&gt;
|constants&lt;br /&gt;
|spec=The email event is triggered as a result of calling [[llGetNextEmail]] when there is an email that matches [[llGetNextEmail]]&#039;s optional filters. The first email that matches the filters is removed from the email queue and its data is used as the parameters for this event. If no email matches the filters but the queue is not empty this event is not triggered. Besides the effects of filtering, the email queue is {{HoverText|FIFO|First In First Out}}.&lt;br /&gt;
|caveats=&lt;br /&gt;
* The email queue is limited to 100 emails, any email after that is bounced.&lt;br /&gt;
* The message field may have a maximum of 1000 single-byte characters. This count includes the header information (&#039;&#039;&#039;address&#039;&#039;&#039;, &#039;&#039;&#039;subject&#039;&#039;&#039;, etc).&lt;br /&gt;
* [[llEmail|Emails sent from within SL]] will have their message body prefixed with a header detailing the originating prim. See [[llEmail]] for more details.&lt;br /&gt;
* Due to bug {{Jira|SVC-23}} (present since 2005), objects may stop receiving emails completely until either the region is restarted or the object crosses a region boundary (resetting the script doesn&#039;t help).&lt;br /&gt;
* Due to bug {{JIRA|BUG-229767}}, an object&#039;s email queue can still become suspended until the object crosses a region border (neither a region restart nor a script reset helps). First analysis has revealed a potential workaround, by implementing a delay of about 30 seconds before first trying to send email to a freshly rezzed script - apparently registering the email(...) event handler can take quite some time, and emails arriving prior to said registry process is what gets the entire queue stuck. Official Linden response still pending.&lt;br /&gt;
&lt;br /&gt;
|constants&lt;br /&gt;
|examples=&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetTimerEvent(5.0);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    timer()&lt;br /&gt;
    {&lt;br /&gt;
    //  get next email, don&#039;t filter by sender or subject&lt;br /&gt;
        llGetNextEmail(&amp;quot;&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    email( string time, string address, string subject, string message, integer num_left )&lt;br /&gt;
    {&lt;br /&gt;
    //  if we received an email from an object within Second Life&lt;br /&gt;
        if (llGetSubString(address, -19, -1) == &amp;quot;@lsl.secondlife.com&amp;quot;)&lt;br /&gt;
//      {&lt;br /&gt;
            message = llDeleteSubString(message, 0, llSubStringIndex(message, &amp;quot;\n\n&amp;quot;) + 1);&lt;br /&gt;
//      }&lt;br /&gt;
&lt;br /&gt;
    //  PUBLIC_CHANNEL has the integer value 0&lt;br /&gt;
        llSay(PUBLIC_CHANNEL, message);&lt;br /&gt;
&lt;br /&gt;
    //  if there&#039;s another email in the queue waiting&lt;br /&gt;
    //  get next email, don&#039;t filter by sender or subject&lt;br /&gt;
        if(num_left)&lt;br /&gt;
            llGetNextEmail(&amp;quot;&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_events&lt;br /&gt;
|also_functions={{LSL DefineRow||[[llEmail]]|}}&lt;br /&gt;
{{LSL DefineRow||[[llGetNextEmail]]|}}&lt;br /&gt;
|also_articles&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes=&lt;br /&gt;
For tips on how to process emails sent from within SL, see the entry on [[llEmail#Prim2Prim_Email|llEmail]].&lt;br /&gt;
|mode&lt;br /&gt;
|deprecated&lt;br /&gt;
|cat1=Email&lt;br /&gt;
|cat2&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Fenchurch Oh</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Template:Issues/BUG-229767&amp;diff=1209756</id>
		<title>Template:Issues/BUG-229767</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Template:Issues/BUG-229767&amp;diff=1209756"/>
		<updated>2020-12-15T21:16:10Z</updated>

		<summary type="html">&lt;p&gt;Fenchurch Oh: Added new JIRA entry&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Issues|BUG-229767|Object-to-object email sporadically fails|type=bug|resolution=unres}}&lt;/div&gt;</summary>
		<author><name>Fenchurch Oh</name></author>
	</entry>
</feed>