Saturday, December 8, 2007

Network server stuff

Before I forget! That network vendor code. The forum post is about a concept that simply doesn't work in SL (who would pay 2L for a drink, nevermind a drink that you "finish" and kills itself?), but the posted code in response to the question is beautiful.

Things of MASSIVE NOTE. Do not, ever, take your server into your inventory. If you need to move it, select Wear from the pie menu and attach it to your bod, go where ever you need to, and Drop it. Do NOT detach. You need to keep it in world at all times, because the UUID will change otherwise, which means everything breaks. Everything. So, this is dangerous in a "shit. I got kicked from my land and everything returned to me" kind of way. Just like onRez vendors and such, it has to be existent in world to work- which means attaching it to yourself and wearing it only works so long as you are logged in. The onRez vendors get around the unique UUID thing, but they've also got waaaaay more of a backend, I'm sure it's to do with contacting the outside server, which keeps track of things and updates when necessary (I would assume SLX has the same general rules, but I've only the experience with onRez. No listing fees = love). This only contacts the one thing in world, so it needs to know how to find it, they use a proxy to filter through, I'm sure.

Also note: 2 code chunks here. First chunk = server. Second chunk = on touch give all items from server. This also needs a little modding to work, period, so don't just copypaste and expect magic to happen (it's just plugging in the UUID from yours in the client code though, assuming you want it to work as is). Thankfully it's actually a reasonably straightforward bit of code, other than all that bloody nesting for the item giving, that I ended up stripping out anyway.


Server Code:

// Distributed item giver (I made it to use with my store landmarks, since I kept having to update multiple vendors)
// You do not need to change anything in this script, just put your items in the server prim that you want handed out when the "giver" prim is touched.
//
// NOTE: THE UUID OF THE SERVER MUST NEVER CHANGE! If it does you'll need to update ALL the child scripts. This means you can NEVER pickup the server prim.
// A simple way to move the server is to right-click the prim, and select "wear", "right hand",
// proceed to teleport or fly to your new location, right-click the prim again and select "DROP",
// (NOT DETACH! if you detach it will move into your inventory and the unique UUID will be lost)
//
// Lasivian Leandros

string gServerKey = "";
list inventory_types = [INVENTORY_BODYPART,INVENTORY_CLOTHING,INVENTORY_LA NDMARK,INVENTORY_NOTECARD,INVENTORY_OBJECT,INVENTO RY_SCRIPT,INVENTORY_SOUND,INVENTORY_TEXTURE];
integer j;
integer k;
integer type;
integer typecount;
string objectname;



default
{
     on_rez(integer i)
     {
          llResetScript();
     }

     state_entry()
     {
          gServerKey = llGetKey();
          llSetObjectDesc(gServerKey);
          llSetText(llGetObjectName() + "\n Key: "+ gServerKey,<0,1,0>,1.0);
          llSetTimerEvent(2.5); // I would not speed this up beyond one e-mail check per 2.5 seconds, it's laggy enough as it is.
     }

     touch_start(integer total_number)
     {
          gServerKey = llGetKey();
          llSetText(llGetObjectName() + "\n Key: "+ gServerKey,<0,1,0>,1.0);
          llInstantMessage(llDetectedKey(0), "Update Server Key is: " + gServerKey);
     }

     email(string time, string address, string subj, string message, integer num_left)
     {
          key target = subj;
          // This allows you to test the system without getting all the junk it's setup to give out
          if (target == llGetOwner())
          {
               llOwnerSay("Touch received on a client prim from you.");
               //return; // If you want to get copies of the given items yourself uncomment this line
          }

          integer total_number = 1;
          //gMessageList = llParseString2List(message, ["\n", "Object-Name: ", " Update", " System"], []);//Break up the content of the e-mail.
          integer i;
          for (i=0;i < total_number;i++)
          {
               integer inventory_count = llGetListLength(inventory_types);
               string myname = llGetScriptName();
               for (j=0; j < inventory_count;j++)
               {
                    type = llList2Integer(inventory_types,j); // get the next inventory type from the list
                    typecount = llGetInventoryNumber(type); // how many of that kind of inventory is in the box?
                    if (typecount > 0)
                    {
                         for (k=0; k < typecount;k++)
                         {
                              objectname = llGetInventoryName(type,k);
                              if (objectname != myname) // don't give self out so the user doesn't get fifty thousand copies.
                              {
                                   llGiveInventory(target,objectname);
                              }
                         }
                    }
               }
          }
     }

     timer()
     {
          llGetNextEmail("", ""); // check for email with any subject/sender
     }
}




Client Code:


//This half the the setup is dead simple, it just sends the key of the person that touched the prim this script is in off to the server, which then distributes the items inside it.

string gTargetKey = ""; // Update this with the UUID of your server prim.
//string gTargetKey = "b041bc00-3d6a-41f7-f65d-81aa36093fca"; //uncomment out this line to see how it should work if you're having trouble with your own.

default
{
     touch_start(integer total_number)
     {
          llEmail(gTargetKey + "@lsl.secondlife.com", llDetectedKey(0), "");
     }
}

1 comment:

Lasivian said...

Nice to see my code is actually useful :)

Lasivian Leandros
www.lasivian.com