Send home and ban avs less than description field days old

From Second Life Wiki
Revision as of 17:57, 24 January 2015 by ObviousAltIsObvious Resident (talk | contribs) (<lsl> tag to <source>)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Send home and ban avs less than description field days old

Modified from script: Days Since

--BETLOG Hax UTC+10: 20090909 1421 [SLT: 20090908 2121]

UTC+10: 20090910 1106 [SLT: 20090909 1806] NOTE: I have not tested this at all. Yes really.
Superficially the 'kick their ass out' logic seems to work... and I am likely to get distractred from this for some time, so am posting it here so it's intended purpose/person I wrote it for doesn't get completely forgotten (by me).
If an avatar that is younger than the number of days specified in the prims description field, collides with this prim, they will be sent home, and banned for the number of days it will take till they are old enough to come back.
The script endeavors (by waiting a bit) to make sure that the message it whispers just prior to ejecting them will be present in their history buffer. So they should know what has happened. Banning them ensures that they don't keep trying to return... which would cause the object to load up and spam anyone within 10m with their repeated ejection message.

//==============================================================
// BETLOG Hax
// UTC+10: 20090909 2049 [SLT: 20090909 0349]
// For Bettina Tizzy
//
// HOW?
// Make a prim to cover your entry parcel, so avatars arrive inside the prim.
//  A transparent prim is ideal. 
//  DO NOT link it to anything...unless its to extend the range of this function or to fit a funky shaped entry area.
// Set the prims description field to the number of days old an avatar must be to enter your sim.
//  eg: 30
// Dump this script into the prim.
// If you are not the land owner you MUST deed the prim to the appropriate group.
// Get someone younger than the number of days you entered above to walk into the prim to test. 
//     It will NOT eject the prims owner. But will output all the usual messages. 
//
// WTF?
// Bettina Tizzy asked for this functionality in group chat.
// For some time I have wanted to write something to calculate age of avatars in days, so I googled, found some logic, and rewrote it in LSL.
//
// NOTE:
// Excluding people based entirely on their avatar account age is a bit of a bastard act.
// Therefore people will not like it when it happens to them. So expect this script to cause drama.
// But if you need a script like this, then you are probably accustomed to drama anyway.
//
//----------------------------------
//        **** LICENCE START ****
// http://creativecommons.org/licenses/by-sa/3.0/
//             Attribution licence:
// You must:
//    -Include this unaltered licence information.
//    -Supply my original script with your modified version.
//    -Retain the original scripts' SL permissions. [+c/+m/+t]
// Or:
//    -Link to the wiki URL from which you copied this script.
//       https://wiki.secondlife.com/wiki/Send_home_and_ban_avs_less_than_description_field_days_old
//    -Document: "Uses parts of <scriptname> by BETLOG Hax"
// AND:
//   Credit for original logic : Robert Baruch
//      http://www.jguru.com/faq/view.jsp?EID=14092
//        **** LICENCE END ****
//----------------------------------
// SHARED CONFIGURATION
//----------------------------------
// CONFIGURATION
key         gDataId;
list        gAvList;
//string      gName               = "";
//----------------------------------
// CORE CODE
key         gOwner; //for when its deeded
//----------------------------------
integer f_daysSince(string input)
{   list l = llParseString2List(input, ["-"],[]);
    integer Y = (integer)llList2String(l,0);
    integer M = (integer)llList2String(l,1);    
    integer D = (integer)llList2String(l,2);
    if(M==1 || M==2)
    {   --Y;
        M+=12;
    }
    integer A = Y/100;
    integer B = A/4;
    integer C = 2-A-B; //(or C=0 if you're using the Julian calendar)
    float E = 365.25*(Y+4716);
    float F = 30.6001*(M+1);
    integer age = C+D+(integer)E+(integer)F-1524;
//llOwnerSay("Julian Day = "+(string)age );

    l = llParseString2List(llGetDate(), ["-"],[]);
    Y = (integer)llList2String(l,0);
    M = (integer)llList2String(l,1);    
    D = (integer)llList2String(l,2);
    if(M==1 || M==2)
    {   --Y;
        M+=12;
    }
    A = Y/100;
    B = A/4;
    C = 2-A-B; //(or C=0 if you're using the Julian calendar)
    E = 365.25*(Y+4716);
    F = 30.6001*(M+1);
    return C+D+(integer)E+(integer)F-1524-age; 
}

//==============================================================
default 
{   state_entry() 
    {   gOwner = llGetOwner();
        llVolumeDetect(TRUE);
    }
    collision_start(integer num)
    {   key av;
        do{ av = llDetectedKey(--num);
            if(-1==llListFindList(gAvList,[(string)av]))
                gAvList += [gDataId=llRequestAgentData(av, DATA_BORN), av, llDetectedName(num)];
        }while(num>0);
    }    
    changed(integer change) 
    {   if(change & CHANGED_OWNER)
        {   if(llGetOwner()!=NULL_KEY)
                gOwner = llGetOwner();
        }
    }
    dataserver(key queryid, string data)
    {   integer i = llListFindList(gAvList,[queryid]);
        if(-1<i)
        {   integer age = f_daysSince(data);//YYYY-MM-DD
            integer limit = (integer)llGetObjectDesc();
            if(limit>0 && age<limit)
            {   key av = (key)llList2String(gAvList,i+1);
                if(av!=NULL_KEY)
                {   string name = llList2String(gAvList,i+2);
                    float duration = 24.0*(limit-age);
                    string oldName= llGetObjectName();
                    llSetObjectName("");
                    llWhisper(0,"/me ☠: Sorry "+name+" Your account is too new."
                        +"\nPlease feel free to come back in "+(string)((integer)(duration/24))
                        +" days when you will be above our minimum required account age of "
                        +(string)((integer)limit)+" days.");
                    list data = llGetObjectDetails(llGetKey(), ([OBJECT_OWNER, OBJECT_GROUP]));
                    key owner = llList2Key(data, 0);
                    if (owner!=NULL_KEY 
                    || llList2Key(data,1)!=llList2Key(llGetParcelDetails(llGetPos(), [PARCEL_DETAILS_GROUP]),0))
                    {   //is NOT deeded or NOT set to correct parcel group
                    llOwnerSay("/me "+llGetRegionName()+" ☠ Sent Home/Banned: \t"+name
                        +"\t [age: "+(string)age+"/"+(string)limit+"] for "
                        +(string)((integer)duration/24)+" days.");
                    }
                    else if(av!=gOwner)//safer testing
                    {   //actually try to get the message to their history buffer
                        llSleep(1.0/(1.01-llGetRegionTimeDilation()));
                        if(llGetAgentSize(av)!=ZERO_VECTOR)//they may have already left
                        {   llTeleportAgentHome(av);
                            llAddToLandBanList(av, duration);
                        }
                    }
                    llSetObjectName(oldName);
                    gAvList=llDeleteSubList(gAvList,i,i+2);
                }
            }
        }
    }
}
//==============================================================

/*
DERIVED FROM:
http://www.jguru.com/faq/view.jsp?EID=14092

 Question         How can I get the number of days that have elapsed between two Date objects?
Derived from     A question posed by J. Scott Stanlick
Topics     Java:Language, Java:API:Internationalization
Author     Robert Baruch
Created     Feb 14, 2000     Modified     May 29, 2000 


Answer
That depends on what you mean by "between".

If you want to find out the number of 24-hour periods between two Date objects d1 and d2 (d2 > d1) then you would do this:

double days = (d2.getTime()-d1.getTime())/1000/60/60/24;

Since Date.getTime returns milliseconds, you divide by 1000 to get seconds, by 60 to get minutes, by 60 again to get hours, and by 24 to get days.

Sometimes this can cause difficulties, especially in countries that have a form of daylight savings time. For example, in the U.S., there is one day in the Fall which has 25 hours, and one day in the Spring which has 23 hours. An elapsed-number-of-days calculation on Dates falling on one of these days may not give the answer you expect.

Anyway, that's the easy way, and if you're satisfied with that, then read no further.

If, on the other hand, you mean the number of midnight-crossings (so that the number of days elapsed between 11:00 PM and 1:00 AM the next day is 1) then you're better off using the Calendar class and computing the Julian Day.

By the way, don't mistake the Julian Day for the Julian Calendar. The two are different and named after different "Julians".

The Julian Day is defined as the number of days elapsed since Nov 24, 4714 BC, 12:00 GMT Gregorian. The year was chosen as being sufficiently in the past so as not to have negative Julian Days, the date was chosen because of the (in that year) 37-day difference between the Julian and Gregorian calendars (Nov 24, 4714 BC Gregorian would be Jan 1, 4713 BC Julian), and the time was chosen because astronomers do their work at night, and it would be a little confusing (to them) to have the Julian Day change in the middle of their work. (I could be wrong)

Anyway, the algorithm for computing the Julian Day from a Gregorian or Julian calendar date for years 400 AD and above is as follows:

Let the date be Y, M, D, where Y is the AD year, M is the month (January=1, December=12), and D is the day (1-31).

For the following calculations, use integer arithmetic (i.e. lop off the fractional part of any result).

If M==1 or M==2 then Y--, M+=12.
Let A = Y/100
Let B = A/4
Let C = 2-A-B (or C=0 if you're using the Julian calendar)
Let E = 365.25*(Y+4716)
Let F = 30.6001*(M+1)

Julian Day = C+D+E+F-1524.5

There would be a further adjustment for the time of day, but we're not looking at that. If you want your Julian Days to start at midnight, subtract 1524 rather than 1524.5.

And so, your number-of-days-elapsed calculation would look like this:

Calendar c1 = new GregorianCalendar();
Calendar c2 = new GregorianCalendar();

c1.setTime(d1);
c2.setTime(d2);

long j1 = julian_day(c1.get(YEAR),
  c1.get(MONTH)+1, c1.get(DAY));
long j2 = julian_day(c2.get(YEAR),
  c2.get(MONTH)+1, c2.get(DAY));

long days_elapsed = j2-j1;

And this would properly calculate the number of midnight-crossings between 11:00 PM on one day and 1:00 AM the next day. 
/*