• strict warning: Non-static method view::load() should not be called statically in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/views.module on line 906.
  • strict warning: Declaration of views_handler_argument::init() should be compatible with views_handler::init(&$view, $options) in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/handlers/views_handler_argument.inc on line 744.
  • strict warning: Declaration of views_handler_filter::options_validate() should be compatible with views_handler::options_validate($form, &$form_state) in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/handlers/views_handler_filter.inc on line 607.
  • strict warning: Declaration of views_handler_filter::options_submit() should be compatible with views_handler::options_submit($form, &$form_state) in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/handlers/views_handler_filter.inc on line 607.
  • strict warning: Declaration of views_handler_filter_boolean_operator::value_validate() should be compatible with views_handler_filter::value_validate($form, &$form_state) in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/handlers/views_handler_filter_boolean_operator.inc on line 159.
  • strict warning: Declaration of views_plugin_style_default::options() should be compatible with views_object::options() in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/plugins/views_plugin_style_default.inc on line 24.
  • strict warning: Declaration of views_plugin_row::options_validate() should be compatible with views_plugin::options_validate(&$form, &$form_state) in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/plugins/views_plugin_row.inc on line 134.
  • strict warning: Declaration of views_plugin_row::options_submit() should be compatible with views_plugin::options_submit(&$form, &$form_state) in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/plugins/views_plugin_row.inc on line 134.
  • GeSHi library error: sites/all/modules/geshifilter/geshi is not a directory.
  • strict warning: Non-static method view::load() should not be called statically in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/views.module on line 906.
  • strict warning: Declaration of views_handler_field_comment::init() should be compatible with views_handler_field::init(&$view, $options) in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/modules/comment/views_handler_field_comment.inc on line 49.
  • strict warning: Declaration of views_handler_filter_node_status::operator_form() should be compatible with views_handler_filter::operator_form(&$form, &$form_state) in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/modules/node/views_handler_filter_node_status.inc on line 13.
  • strict warning: Non-static method view::load() should not be called statically in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/views.module on line 906.
  • strict warning: Non-static method view::load() should not be called statically in /home/ordinal/ordinalmalaprop.com/engine/sites/all/modules/views/views.module on line 906.

January 2010

An explanation

I felt that I should write a final entry here to clarify recent events and the current situation.

What have you done?

I have removed every building and item of mine from the Grid, most notably, Caledon and New Babbage. (At least, I think I have; there may be a few bits and pieces left scattered about.) Ordinal Enterprises is no longer a functioning operation. I have not abandoned my land - for the moment I will hold onto it. It just won’t contain anything of significance.

I also do not plan to write any more in this Journal for a considerable time, though I may change my mind there.

Does this mean you’ve left Second Life?

In practice, I can't think that I will be around much in the immediate future - though I expect I will pop back occasionally, either in relation to work, or to feed the parcel meters.

My intention in doing these things was not to leave Second Life, but Ordinal Enterprises is (or was) such a significant part of my existence and day-to-day behaviour that without it, I find it hard to imagine what I would do now.

Why on earth would you do that?

This is quite a difficult question, and may not have a coherent answer at all, but I will do my best to produce one. It will, I expect, be very self-indulgent.

The purpose of Ordinal Enterprises

Originally, Ordinal Enterprises was a framework and context for the silly things that I built, providing me with a well-understood means of distribution (i.e. a “shop”) and a Victorianesque mercantile narrative within which the products could exist - which in itself then generated inspiration for further creations. The challenge of competing in the general marketplace, too, was stimulating; the narrative was always the most important part though, a framework in a world that, as is often pointed out, is otherwise a blank slate.

The Increasing Problem

For a while now I have found myself increasingly less productive in terms of producing items and scripts, and this is not for lack of ideas - I have been generating notebooks full of ridiculous concepts which I would then plan out as systems or items, enter onto my Lists of Tasks to begin, not do, avoid looking at for a while and then mark “someday/maybe”.

This is a painful process and I hate it. It makes me feel completely impractical and without any willpower whatsoever, particularly when I looked at the series of items that I had already created, back when the Grid was younger, which sat there as a constant reminder on the ground below my skybox, which I visited less and less frequently.

On the occasions when I entered Second Life at all, I found something to irritate me, and I would become bitter and argumentative and also fail to achieve anything. Quite often this would be a technical issue - rarely a severe one (grid and regions used to be far less stable and reliable, believe it or not) more often one that was just stupid. Alternatively, and increasingly more so recently, it would be a political or social issue arising from dictat or commentary or mistake or some such event. The list of recent topics in this Journal provides examples of the sort of thing.

I am not saying here, by the way, that this is all the fault of Lindens, or anything like that: I have, though, increasingly felt “this world is not for me”, particularly with issues such as the increasing split between “consumer” and “creator”, which I have written about previously.

The actual Removal

I decided yesterday to try once again, this time to clear out those projects which had been hanging around and making me miserable, sometimes for years. Just release the ones which were even vaguely saleable, perhaps for free, and then cross them off my list, mark them “done”. (I even came up with some more ideas for items while I was planning this - I had no intention of coming in to stop.)

Two things happened. Firstly there was the ridiculous business with the Avatars United site - by the way, I don’t blame the site itself for anything, it is quite clear about how it works and I’m sure does a great job in other contexts, what I am criticising is its immediate promotion as being for use in SL, without a thought to identity verification. Anyway, that business. Secondly, later on that evening, I had just finished the release steps for one of the products I had planned, boxing it, adding textures, final checks, even having made a video, and at the last stage I tested it with a friend and it began to show script permission errors.

I’m afraid that something broke at that point. First of all I decided not to release the item after all. Then I decided not to release any of them, and just delete them. And then I looked at the lighthouse and my little shop, and it just seemed to me that all this time I had just been fooling myself, that instead of it being an inspiration it was now a parody of something that I used to deeply enjoy; that I was using it to pretend that I was still enjoying it and that nothing had changed over the years, either in myself or in the wider world. So, I deleted it all.

Are you sure about all this?

No. Not at all. I’m afraid that I just couldn’t come up with any better solution.

Closed for an Indefinite Period

As of today and until further notice, this Journal should be considered Closed; it reflects a particular period of my life that became, in effect, me fooling myself imperfectly. Ordinal Enterprises no longer exists inworld, and none of my products are available any more.

Entries in this journal will still be available for posterity and any use they might be to people.

~*~

There may be a final journal entry at some point containing fuller explanation, but there may also not be.

~*~

No change is planned, incidentally, to the operation of the Twitterbox - I will continue to host the required proxy.

Avatars Unite! As many times as is desired!

The purchase of a site known as "Avatars United" was recently announced by Linden Lab as... well, I am not precisely sure quite what the point was but it was a Great Thing nonetheless. Apparently the aim was to make sure that people with existing identities on the Grid, and therefore on Grid-Related Websites such as the Linden Blogthing, could also be represented on another random site for no apparent reason.

With that in mind I have registered all of my current Second Life identities. I warn anybody who does not wish to know my current "alts" to look away now.

Who I am in Second Life

Well, I did not wish to say so explicitly, but any "Desmond Shang" that you might be dealing with who says that it is not obligatory to buy everything from Ordinal Enterprises in order to enter Caledon is a fraud and not in my existing group of friends - but that fake identity will isolate itself.

Q: I have several avatars on several games. Can I register them all?
A: Yes. Currently Avatars United has no limit on avatars to any given account.
Q: Can I register avatars from games I am not currently playing?
A: Yes, as a matter of fact we hope you will. Do register avatars from games you previously have played and you will allow old friends you previously played with to find you.
Q: Are you verifying that all the posted avatar information is accurate?
A: No. Avatars United is mainly a community for existing groups of friends and as such we believe fake identities will isolate themselves. (Frequently Asked Questions)

The fact that one might apparently register not only a name that has nothing to do with one's actual name, but in fact, a name that has already been registered, I'm sure is just a feature.

(Yes, by the way, it would be trivial to have an inworld check on identity, whereby an avatar confirmed that the "Avatars United" account was indeed theirs by touching a box or some such - and that would just be for residents, anyone connected with LL would no doubt have even more tools available.)

Is the concept of "identity" even thought about, let alone appreciated? Signs point to no.

A Useful Script - "Mass Distribution by List of Names in a Notecard"

I recently had cause to distribute a number of items to a large number of people, whose names I was in possession of a list of, but not, of course, their keys.

The appalling lack of a useful llName2Key function unfortunately makes it a little challenging to send things out, but this is a problem that I have encountered before, and the obvious course of action is to

  1. put all of the items to be sent out into a prim;
  2. add a notecard containing the list of names to which these items are to be sent;
  3. add a script which simply goes through these names, queries one of the several "name2key" databases in existence, and, should it find an appropriate key, sends the items out.

For general use I include such a script herein.

In this I included features which tell one how many lines of the names notecard remain, and an estimate of the how much time remains, as well, though this may or may not be terribly accurate.

I am aware that it could be made considerably faster by the use of subscripts to send the inventory items, but that would make for a rather poor example script; I would prefer to keep the whole affair as simple as possible, in other words, in one script that is put into one prim. The introduction of inventory-giving subscripts is left as an exercise for the keen student.

~*~

As a further note, a future script using this sort of system to be published here will be a vendor that optionally sends the item to another person - in other words, a gift-giver that allows people to purchase copy/no-trans goods for others, which will allow those who had been forced to rely upon Xstreet for this the opportunity to abandon the dratted site.

Mass distribution script

Code summary: 

Sends inventory contents to each named individual on a list, by trying to get their key from a series of databases. This would be so much easier if there was a name2key function. But there isn't.

To use this script: place it in a prim, along with some other items that you want to send to people, and a notecard called "Names" which has a list of avatar names to send items to, one per line without spaces before or after them. (Blank lines will be ignored; anything else, and the script will try to find the line as if it were a name, and fail, and tell you that it has failed.)

Then, touch to start sending. There will be a display of names left to check and estimated time remaining.

There is no way of determining whether an object has been successfully sent by script, or whether somebody was in busy mode (this is the usual culprit when people complain of not receiving an item - either that, or they did receive it but can't find it) or declined the item. My apologies.

// Mass distribution script // Ordinal Malaprop 2010-01-15 11:29 //..................................................................... // Sends inventory contents to each named individual on a list, by trying to get their key from a series of databases. This would be so much easier if there was a name2key function. But there isn't. // To use this script: place it in a prim, along with some other items that you want to send to people, and a notecard called "Names" which has a list of avatar names to send items to, one per line without spaces before or after them. (Blank lines will be ignored; anything else, and the script will try to find the line as if it were a name, and fail, and tell you that it has failed.) // Then, touch to start sending. There will be a display of names left to check and estimated time remaining. // There is no way of determining whether an object has been successfully sent by script, or whether somebody was in busy mode (this is the usual culprit when people complain of not receiving an item - either that, or they did receive it but can't find it) or declined the item. My apologies. // The original script can be found at http://ordinalmalaprop.com/engine/code/mass-distribution-script //--------------------------------------------------------------------- // LICENCE - Creative Commons "Attribution" 3.0 // http://creativecommons.org/licenses/by/3.0/ // Basically use it how you like, but if you do, please include a mention somewhere of me, and if possible a link to the original script. //--------------------------------------------------------------------- // Globals and constants // Configurable string NAME_NOTECARD = "Names"; // Change this if you want to call the notecard with your list of names on it something else. float TIMEOUT = 10.0; // There is no particular reason you would change this but you might wish to perhaps. integer TEST = FALSE; // change to TRUE to just run through the names in your notecard without sending anything // Not configurable - leave these alone key gQuery = NULL_KEY; string gAvName = ""; integer gLine = 0; integer gNumberOfLines = 0; list gItems = []; list gNotFound = []; integer gQuerySource = -1; //--------------------------------------------------------------------- // Functions // Looks for the next name on the list get_next_name() { llSetTimerEvent(TIMEOUT); if (gNumberOfLines == 0) { llSetText("Checking list size", <1.0, 1.0, 0.0>, 1.0); gQuery = llGetNumberOfNotecardLines(NAME_NOTECARD); } else { gQuery = llGetNotecardLine(NAME_NOTECARD, gLine++); update(); } } // Updates the prim display update() { integer line = gLine - 1; integer done = llRound(100 * line / gNumberOfLines); float x = (float)done / 100.0; llSetColor(, ALL_SIDES); llSetText((string)done + "% done (" + (string)line + "/" + (string)gNumberOfLines + ")\nRemaining time: " + time_left(line), <1.0, 1.0, 0.0>, 1.0); } string time_left(integer line) { if (gNumberOfLines == 0) return "unknown"; if (line == 0) { llResetTime(); return "unknown"; } float timePerLine = llGetTime() / line; return minutes_seconds(llRound(timePerLine * (float)(gNumberOfLines - line))); } string minutes_seconds(integer seconds) { if (seconds < 60) return (string)seconds + "s"; integer minutes = seconds / 60; seconds -= minutes * 60; string msg = (string)minutes + "m"; if (seconds > 0) msg += (string)seconds + "s"; return msg; } // This function sends queries to web databases to get keys from names. It moves through a series of different ones based on the current value of gQuerySource - if a query fails, it moves to the next one. I think that three different databases should eventually provide a reasonable result. Note that you can move the databases around according to your preference by cutting and pasting within the "if ... else" blocks. make_key_request(string name) { gAvName = name; llSetTimerEvent(TIMEOUT); gQuerySource++; string source = ""; if (gQuerySource == 0) { // modularsystems.sl name2key service source = "lawlinter.net"; gQuery = llHTTPRequest("http://lawlinter.net/secondlifeutility/name2key.php5?name=" + llEscapeURL(name), [HTTP_METHOD, "GET"], ""); } else if (gQuerySource == 1) { // visiontech - slow, but claims to be complete source = "VisionTech"; name = llDumpList2String(llParseString2List(name, [" "], []), "_"); gQuery = llHTTPRequest("http://vision-tech.org/name2key/search.php?name=" + name, [HTTP_METHOD, "GET"], ""); } else if (gQuerySource == 2) { // w-hat source = "w-hat"; gQuery = llHTTPRequest("http://w-hat.com/name2key?terse=1&name=" + llEscapeURL(name), [HTTP_METHOD, "GET"], ""); } if (source == "") { // failed, try a new one llOwnerSay("All sources failed to find a key for '" + gAvName + "', moving on."); gQuerySource = -1; gNotFound = (gNotFound = []) + gNotFound + [gAvName]; get_next_name(); } else if (gQuerySource > 0) { llOwnerSay("Trying " + source + " database..."); } } // Gets all of the items to be sent, and sets text based on what they are list get_item_list() { integer f = llGetInventoryNumber(INVENTORY_ALL) - 1; list items = []; string thisScript = llGetScriptName(); while (f >= 0) { string name = llGetInventoryName(INVENTORY_ALL, f); if (name != "" && name != thisScript && name != NAME_NOTECARD) { items = (items = []) + items + [name]; } f--; } if (llGetListLength(items) > 0) { string msg = "Sending:\n" + llDumpList2String(items, "\n"); if (TEST) msg = "[TEST] Not " + (msg = "") + msg; llSetText(msg, <0.0, 1.0, 0.0>, 1.0); } else { llSetText("No items found to send", <1.0, 0.0, 0.0>, 1.0); } return items; } // Sends the actual items to a particular avatar send_items(key id) { integer f = llGetListLength(gItems) - 1; llOwnerSay("Giving items..."); while (f >= 0) { string name = llList2String(gItems, f); if (TEST) llSleep(2.0); else llGiveInventory(id, name); f--; } llOwnerSay("Done."); } //--------------------------------------------------------------------- // Main // The default state is "not sending anything right at this moment". default { state_entry() { llSetText("", <0.0, 0.0, 0.0>, 1.0); llSetColor(<1.0, 1.0, 1.0>, ALL_SIDES); gItems = get_item_list(); llOwnerSay(llGetScriptName() + " ready, touch to start sending inventory."); } on_rez(integer p) { llResetScript(); } touch_start(integer n) { if (llGetListLength(gItems) == 0) { llOwnerSay("Nothing suitable in this item's inventory to give!"); } else if (llGetInventoryType(NAME_NOTECARD) == INVENTORY_NONE) { llOwnerSay("You need a notecard called '" + NAME_NOTECARD + "' in this item for it to send its contents to people."); } else { state sending; } } changed(integer change) { if (change & CHANGED_INVENTORY) llResetScript(); } } // In "sending" state, we are actually reading names, finding keys and sending things out. state sending { state_entry() { gNumberOfLines = 0; gLine = 0; gNotFound = []; gQuerySource = -1; llOwnerSay("Beginning send - take into inventory to stop this."); get_next_name(); } on_rez(integer p) { llResetScript(); } dataserver(key query, string data) { if (query != gQuery) return; if (data == EOF) { llOwnerSay("All notecard lines scanned."); state default; } else if (gNumberOfLines == 0) { gNumberOfLines = (integer)data; get_next_name(); } else if (data != "") { make_key_request(data); } else get_next_name(); } http_response(key query, integer status, list metadata, string data) { if (query != gQuery) return; llSetTimerEvent(0.0); key avKey = (key)data; if (llStringLength(data) == 36 && avKey != NULL_KEY) { llOwnerSay("Found key for '" + gAvName + "' : " + (string)avKey); gQuerySource = -1; send_items(avKey); } else { llOwnerSay("ERROR: Could not find avatar name '" + gAvName + "' in database."); make_key_request(gAvName); } get_next_name(); } timer() { llOwnerSay("ERROR: timed out looking for avatar name '" + gAvName + "'."); make_key_request(gAvName); } state_exit() { llOwnerSay("Names not found: " + llList2CSV(gNotFound)); float time = llGetTime(); llOwnerSay("Total time: " + minutes_seconds((integer)time) + " seconds (" + (string)(time / gNumberOfLines) + " seconds per line)."); } }