LSL Protocol/Restrained Life Relay/Mouselook

Put this script into a small child prim of the relay. It will resize this prim to full size if the victim does not stay in mouselook while urged to do so.
Note: @thirdview=n is an inoffical command. It has never been part of the specification and might be replaced by a meta command.
== Change Log ==
=== 1.040 ===
* multi prim relay support
== Code ==
<lsl>
// Mouselook script for RestrainedLife Viewer Relay
//
// Code by Maike Short based on an inoffical protocol extension by Monica Jewell
//
// Please reports problems to 
// https://wiki.secondlife.com/wiki/LSL_Protocol/Restrained_Life_Relay/Bugs_and_Pendings_Features
//
// This script is provided AS-IS, OPEN-SOURCE and holds NO WARRANTY of accuracy, completeness 
// or performance. It may be distributed in its full source code with this header and 
// disclaimer and is not to be sold without permission. Optionally it may be distributed
// in a 'no mod' form within Second Life™ PROVIDED that either a link to the full source
// IS provided (ie. this page or a .zip or .rar) within the object the code is contained 
// AND/OR a off-world contact point (ie. email) that the source code may be requested from.
// This somewhat unusual (no-mod) distribution is allowed to maintain the integrity and
// reliability of the creator reference of in-world objects (scripts). Changes and
// improvement to this code must be shared with the community so that we ALL benefit.
integer RLV_LINK_CHANNEL = -1373421301;
list mouselookRequests = []; // a list of prims that requested mouselook enforcement
integer mouselookTicks = 0; // count the timer ticks until the next reminder message is printed again
integer mouselookLast = TRUE; // was the sub in mouselook during last check?
// is mouselook required
integer mouselookRequired()
{
 return llGetListLength(mouselookRequests) > 0;
}
// punishes the sub
punish()
{
 // ensure that we are attached to the HUD
 // we don't want a 10x10x10 black prim in world
 integer point = llGetAttached();
 if ((point < ATTACH_HUD_CENTER_2) || (point > ATTACH_HUD_BOTTOM_RIGHT))
 {
 return;
 }
 llSetPrimitiveParams([PRIM_SIZE, <10, 10, 10>]);
 llSetAlpha(1, ALL_SIDES);
 llOwnerSay("@detach=n,edit=n");
}
// undos the punishment
lift()
{
 llSetPrimitiveParams([PRIM_SIZE, <0, 0, 0>]);
 llSetAlpha(0, ALL_SIDES);
 llOwnerSay("@detach=y,edit=y");
}
// releases mouselook requirement
release()
{
 llSetTimerEvent(0);
 mouselookTicks = 0;
 lift();
}
// check whether the avatar is in mouselook and take appropriate actions
handleMouselook()
{
 // first of all check that mouselook is enforced
 if (!mouselookRequired())
 {
 release();
 return;
 }
 // good, now check that the avatar is in mouselook
 integer data = llGetAgentInfo(llGetOwner());
 integer mouselookIn = (data & AGENT_MOUSELOOK);
 if (!mouselookIn)
 {
 if (mouselookTicks % 60 == 0)
 {
 llOwnerSay("Go to mouselook or stay blind.");
 }
 mouselookTicks++;
 }
 // if we are still in mouselook, or if we are still not in mouselook,
 // the HUD will still be in the correct state
 if (mouselookIn == mouselookLast)
 {
 // no need to mess with the prim
 return;
 }
 // something has changed, either punish or lift the punishment
 if (mouselookIn)
 {
 lift();
 }
 else
 {
 punish();
 }
 // remember whether we punished or lifted the punisment
 mouselookLast = mouselookIn;
}
// process the request to start mouselook enforcement
processMouselookRequest(integer sender)
{
 if (llListFindList(mouselookRequests, [sender]) < 0)
 {
 mouselookRequests += sender;
 }
 mouselookLast = TRUE;
 handleMouselook();
 llSetTimerEvent(1);
}
// process the request to release mouselook enforcement
processReleaseRequest(integer sender)
{
 if (sender == LINK_ROOT)
 {
 // a clear from the root prim means, that the complete relay was reset
 mouselookRequests = [];
 }
 else
 {
 integer pos = llListFindList(mouselookRequests, [sender]);
 if (pos > -1)
 {
 mouselookRequests = llDeleteSubList(mouselookRequests, pos, pos);
 }
 }
 // if no one wants mouselook anymore, release it
 if (!mouselookRequired())
 {
 release();
 }
}
default {
 state_entry()
 {
 llSetColor(<0, 0, 0>, ALL_SIDES);
 llSetTexture(TEXTURE_BLANK, ALL_SIDES);
 release();
 } 
 on_rez(integer i)
 {
 if (mouselookRequired())
 {
 llOwnerSay("Go to mouselook or stay blind");
 }
 // get mouselook code into correct state
 mouselookLast = TRUE;
 handleMouselook();
 }
 // handle commands
 link_message(integer sender, integer channel, string message, key id)
 {
 if (channel != RLV_LINK_CHANNEL)
 {
 return;
 }
 message = llToLower(message);
 if ((message == "@thirdview=y") || (message == "@clear"))
 {
 processReleaseRequest(sender);
 }
 else if (message == "@thirdview=n")
 {
 processMouselookRequest(sender);
 }
 }
 // check if the sub obeys while mouselook is enforced
 timer()
 {
 handleMouselook();
 }
 // we don't want a nasty surprise for the next owner
 changed(integer change)
 {
 if (change & CHANGED_OWNER)
 {
 llResetScript();
 }
 }
}
</lsl>