aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/TODO
blob: 9cd4cdf2b94b3a8e58b8fe473e8c6d729f90de9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
FIXES -

    Black bug
-------------

Evas3D and Elementary don't get along well with more than one mesh that
has textures.  After hiding the window, by iconifying it, or moving to a
different virtual desktop for a bit, or after waiting a few minutes. 
The textures are replaced by blackness, a shiny blackness sometimes. 
Only seems to happen in Elementary.


    Evas_3D pick bug
--------------------

evas_canvas3d_mesh_frame_vertex_data_copy_set() sets the meshes aabb,
but evas_canvas3d_mesh_frame_vertex_data_set( , EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION, )
doesn't, though it tries to.


    Use Lua consistently
------------------------

I noticed that the internal messages seem to be mostly LSL, but really
should be Lua at this early stage.  LSL should be kept strictly inside
the LSL scripts.  This might get tricky.  Also, massage these notes into
docs later.

LuaSL				Script server in C.
  Opens a socket for script commands.
    Accepts "compile(...)", "run(...)", and "exit()",
      "run(...)"
        Creates a script via scriptAdd(), with send2server included.
        Either runs it directly, or stuffs it into the worker thread queue.
    otherwise send2script(SID, command)
	NOTE: treats "return ..." different to "function(...)".

  send2script()			C function that adds the message to the scripts messages, then runs the script worker thread.
    Runnr.c

  send2server()			C function that sends the message to the love server.  send2parser() will intercept the send2() call.
    LuaSL_main.c
	takeScript(me);
	send2(me->client, me->SID, message);
	releaseScript(me);
  send2parser()			C function that intercepts send2(), and deals with time, script states, and resetting scripts.

Runnr.c
  worker thread
    Starts or resumes the script running.  If there's a message, push it as an argument.
    Expects the script to eventually call Runnr.receive().
  Runnr.receive()
    Does a Lua yield, which will return once there is a message for this script.
  Runnr.send()
    Either send2script(SID, message), or send2server(message)

lib/LSL.lua			Lua script that supplies all the LSL functions, and the basic LSL script support.
  LSL.Lua runs the main loop of each LSL script.
    waitAndProcess(false, "LSL.mainLoop")
      LSL.lua assumes that it gets Lua messages from Runnr.receive(), and tries to run them via loadstring() and pcall().
      "start()" while paused is handled special, and likely should stay that way.
      Sets the environment to that of LSL.lua, unless it's an event, before calling pcall.
      Says it runs the return, but also sends the return via Runnr.send(nil, result1), which is commented out.
        What should happen is that instead of "return somevalue", it's just "someValue", but that could be "someValue + thingy".
        So, execute it, return the result if returnWanted.
      Sooo, doesn't do anything with the result, unless returnWanted.
      Returns whatever the pcall returns, if returWanted, which we don't during the main loop.
  Some of the ll functions are defined as a wrapper around waitAndProcess, that first Runnr.send(nil, ...) the function call details.
    Which is currently the LSL version of the name, with LSL arguments.
    NOTE: the wrappers don't currently deal with casting arguments, but should, and it has enough info to do so.

love.c				World server in C.
  Runs / connects to LuaSL server.
    Sends "compile(...)" commands for each script it finds.
    Accepts "compilerError/Warning(...)", "compiled(...)"
      Once "compiled(...)", sends "run(...)" commands for them.
    otherwise, a whole bunch of LSL functions, mostly faked, some simply sent to the client.
    otherwise just log it as INFO.
  Opens a socket for client stuff.
    For each new client -
      send2(client, "loadSim(...)"
      Accepts "events.touch_start()", and "events.listen()"
        passing them onto LuaSL, though with some extra info if it's a touch -
	    send2(ourGlobals->serverLuaSL, me->SID, "events.detectedKeys({\"%s\"})", ownerKey);
	    send2(ourGlobals->serverLuaSL, me->SID, "events.detectedNames({\"%s\"})", ownerName);
	    send2(ourGlobals->serverLuaSL, me->SID, "events.touch_start(1)");
      otherwise complains with a WARNING.
  At some point -
    send2(LuaSL, SID, "return ...")
    send2(LuaSL, SID, "events.*(...)")
    send2(LuaSL, ownerKey, "exit()")

extantz.c			Client in C and lua.
  Runs / connects to love server.
    Accepts a bunch of LSL functions, "loadSim(...)",
      llSay() and friends, llDialog()
    otherwise log as INFO.
  At some point -
    send2(love, SID, "events.touch_start(1)")
    send2(love, SID, "events.listen(...)")


What should happen (though leaving the Nailer step for much later, so use Lua instead of Nails ) -
  LuaSL
    converts LSL into Lua
    runs everything in the Lua domain
    sends Lua to the LuaNailer
      deal with LSL -> Lua argument casting
    accepts Lua from the LuaNailer
      deal with Lua -> LSL return value casting
  LuaNailer
    converts Lua <-> Nails
  love
    accepts Nails commands from LuaNailer
      sends some of them onto extantz
      sends some back in response
    relays / modifies Nails commands from extantz to LuaSL
  extantz
    accepts Nails commands from love
    sends Nails commands to love

What does this internal Lua look like?
  The internal Lua should be more SledjHamr flavour than LSL flavour, so we get a chance to design it right.
  What's right though?

  Handled by extantz -
    For all of these, we need to know who / what sent it, and when,
      also where the sender was at the time for some of these.
    llSay(integer channel, string text)+
      also
        llOwnerSay(string text)
        llRegionSayTo(key target, integer channelID, string text)
          Actually, if this sends messages to objects, then love should handle it,
          only handled here if it's for a person.
        llInstantMessage(string user, string message)
    llDialog(key avatar, string caption, list arseBackwardsMenu, integer channel)
    llListen(integer channel, string name, key id, string msg)
  Sent from extantz -
    events.listen(integer channel, string name, key id, string message)
    events.touch_start(integer num_detected)
  Handled by love -
    object information get
    avatar info get
    llRequestPermissions()
    position and rotation get
    alpha get
    inventory and link details get
    free memory get
    "notecard" get
  Sent from love -
    events.detected*({"",})
    events.*(...)
    return ...
  Handled by the script server -
    time stuff get / set
    script state get / set

Communication
  world.say(key source, vector location, integer timestamp, text message, string filter, ...)
    Source is the key of the avatar / object / script saying things.
    Location is the location of that source in world at the time of the timestamp.
      Though in the case of IMs, avatar might not be in world at the time.
    filter is a comma separated string -
      "<Xm>,<key>,<channel>"
      llSay()+ include <channel>, and a distance restriction <Xm> in meters.
        The distance restriction is one of a fixed four in LL - whisper, say, shout, region.
        What these mean depends on how an OpenSim region is configured, or the default SL values.
        So stuff in the SL values in LuaSL, convert to OS values in love, calculate objects / avatars within that radius in love, then pass it onto the objects scripts, or the avatar's client.
        "Region" is the default, in other words, no distance restriction.
      <key> would be a persons ID for llOwnerSay() and llInstantMessage(), but object/person ID for llRegionSayTo()
      <channel> would be a channel name / number.  LSL only has numbers, with two being fixed function.  We can relax that and add strings.
      NOTE: llRegionSayTo() includes both <key> and <channel>.
      llDialog() includes a string and a list, er I mean table, Lua table.

  Objects that are interested in things said register listeners with love, and get events.listen()'s sent to them.
    Some sort of filter is needed for this as well.
    listen(string filter, string text, integer flags)
      filter - <Xm>,<key>,<channel>,<self>
        In this case, <Xm> isn't actually needed by any LSL function, but I include it for completeness sake.
        <self> means do listen to yourself, which is usually not what you get in LSL, but I'm leaving that option open.
      text   - a string to match, might be a regex
      flags  - include the regex flags from the OS version
      The last two arguments are optional.  Flags is itself optional if text is there, defaulting to "not a regex".
      returns a <handle>
        can be in/actived, or removed.
    This includes llDialog() and llTextBox().
      Note that these two are LL specific things, we use skang for the more general case.  Though both need client side support, which means love has to pass these things around.

  events.say(key source, vector location, integer timestamp, text message, string filter, ...)

  Link messages include the number of the link (to or from, depending on which end you are at), a number, a string, and a key.
    These are entirely internal to LuaSL though, except they bounce up to love to get to other prims in the link set?

purkle registers a listener, with no filter.
llDialog's client side sends a say() to love.
  Normally, that wont be bounced back to extantz.
  SL and OS however, bounce all channels across the viewer, which is why some of them can peek at other channels.
  Which is why purkle registers with no filter, gotta gettem all.
  Later we should default to just channel 0.

Soooo, every one sends their say() commands to love.  Love decides who to send listen() events to, which may include sending back to the source.

May need to start name spacing Lua stuff.
  scripts.compile(), scripts.run(), scripts.reset() scripts.listen() which would include avatar's clients registering via purkle pretending to be a Lua script,
  world.say(), events.say()

The only place where there is any ambiguity is LuaSL.
Purkle accepts events.say() from love, LSLGuiMess sends world.say() to love.
Love routes world.say()'s around, even back to the source if needed, sending them as events.say().
LuaSL sends world.say() to love.  LuaSL accepts events.say() from love for scripts.
  When a say() comes in, it's executed, which triggers the say() that sends to love.  OOPS!!!!
  world.say() -> events.say()

More generic event system?
  Events are different from state changes.  The Nails web page mostly
  talks about the state of objects, and changing them.  Events are for a
  variety of things, not all of which can be represented by a state
  change message.

  There are other events flying around.
    BASIC event		Just send it to LuaSL, it loops through all scripts, sending the event to them all if they have an event function in their current state.
    REGISTER event	Script has to register for these events with love.  Can have filter.  love loops through all registered "scripts", applies filters, sends events.
    REQUEST event	Script has to request an event from love.  Can have a filter.  Love sends event straight back to the script.  Once.
			  This covers the "wait for return value" case as well.  events.return()?
  touch_start goes from extantz to LuaSL, via love.  Most of the rest go from love to LuaSL I think.  state_entry, state_exit are internal to LuaSL, timer should be.
  All manner of arguments sent to events.
    Some of them include the llDetected*() functions for getting more info.
    So we need some way of sending arbitrary data, as well as a bunch of fixed data, over the network when we send events.
  Listen events are common?
    collision, land_collision, not_at_*_target , and touch might be ongoing?
      llCollisionFilter(string name, id, integer accept)
      llTarget(vector position, float range)
      llTargetRemove(integer number)
      llVolumeDetect(integer detect)
    Sensor and no_sensor might be common, but you request those, your silly fault, they have filters though.
      llSensor(string name, string id, integer type, float range, float arc)
      llSensorRepeat(string name, string id, integer type, float range, float arc, float rate)
  Event types can have filters?  Events can be types?  In other words, generic filter system, attach say filters to say type events, etc.
    Figure this all out as we go along.

parseStream() / send2() both -
  lookup command in conn->commands
    if found, use that found function pointer
  else
    try conn->unknownCommand for the function pointer
  call the function pointer
  or bitch / send to love

LuaSL
  open a server stream
    incoming -> parseStream()
      commands	scripts.compile(), scripts.run(), scripts.return(), etc.
      unknown	events.eventName() -> loop through each script looking for "function" = type(currentState.[eventName])
		otherwise send2script()
      bitch
    outgoing -> send2()
      commands	scripts.state(), scripts.reset(), scripts.link_message(), and timer.*() commands currently in LuaSL_main.c->send2parser()
      unknown	NULL
      actually send it

love
  open a stream to LuaSL
    incoming -> parseStream()
      commands	various compiling results, world functions, and event registrations / requests
      unknown	NULL
      bitch
    outgoing -> send2()
      commands	NULL
      unknown	NULL
      filter	as needed
      actually send it
  open a server stream
    incoming -> parseStream()
      commands	various world functions, and event registrations
      unknown	NULL
      bitch
    outgoing -> send2()
      commands	NULL
      unknown	NULL
      filter	as needed
      actually send it

extantz
  open a stream to love
    incoming -> parseStream()
      commands	events.say(), events.dialog(), events.textBox(), events.loadSim()
      unknown	check for valid Lua
      bitch
    outgoing -> send2()
      commands	NULL
      unknown	NULL
      actually send it



    LuaSL crashes
-----------------

Hmmm, empty functions get no end, that's NOT legal in Lua.

    Project paths
-----------------

The executables currently live in ...../SledjHamr.
  Test executables stay in the src directory.
Media and other data in SledjHamr/media (includes the test sim and Irrlicht examples).
External libraries are in SledjHamr/libraries (Irrlicht and lemon).
  Irrlicht is statically linked, so except for it's media, we don't need it at run time.
    We could probably move the Irrlicht examples we actually use (all test data anyway) to Test sim.
  Lemon is only used at build time.

Builders should be able to -
  put binaries in /usr/local/bin
  put libraries - /usr/local/lib/SledjHamr
  put media in /usr/local/share/SledjHamr
If they don't, those things should be in the build directory, where they are now.

User should be able to -
  Run sims from where ever they like.
  Write GuiLua modules that reference media that is where ever it is.
    Normally media would come along with the module.
    So on disk modules would include media in the same directory as the module.
    In world modules would be in some object, and the media should be in that object to.
    Client side modules from the net ... dunno yet.
  Write their own skins, using their own media.

SOOOO ...
  install.lua should - 			(doesn't exist yet)
    SledjHamr binaries	-> prefix .. '/bin'
    SledjHamr/libraries	-> prefix .. '/lib/SledjHamr'
    SledjHamr/media	-> prefix .. '/share/SledjHamr/media'
      This should not include data that could be changable, so maybe the test sim should move elsewhere?
        LuaSL at least puts compiled scripts in the test sim.
        Nails will eventually make changes to the test sim during testing.
        For now, we don't care, there's no actual installing going on.
    SledjHamr/locale	-> prefix .. '/share/SledjHamr/locale'

    ~/.SledjHamr/
      Contains an index.omg, and / or a bunch of sim directories / OAR files / etc..
    ~/.SledjHamr/.downloaded/
      Contains downloaded sims in their original format, like OAR files.
    ~/.SledjHamr/.cache/ unpacked/ converted/ sha1/ types/ compiled/
      Contains various cached stuff that can be deleted at any time.
        unpacked/	is for anything that's in an archive file, unpack it all in there.
        converted/	is for anything that is converted to SledjHamr formats, from legacy formats.
        sha1/		is for the sha1 sums of asset files, and other details?
        types/		is for storing the types of asset files?
        compiled/	is for translated and compiled scripts.


Irrlicht is flickering like crazy.  Hmm, might be Irrlicht's fault,
mostly it flickers to black, but I've seen it flicker to the first frame
of the GL demo.  On the other hand, it shows the Elm background usually.

GL viewport aspect ratio should remain stable through resizes.


FEATURES -

Er, all of them I think.  B-)

Make the existing toolbar / tab thingy a bit more tab like, and have the
scroll in effect be position / direction aware.  Combining window title,
menu, top level tabs, and toolbar widgets might be good.  Perhaps auto
spreading across two lines (menu + tools / tabs) on window shrinkage
first before going to the "More.." thing (for both tabs and tools).

Need pie menus!

Generic scrolling text area, with time stamps, clickable URLs (including
internal links to profiles and stuff), logging to file, reading history
from file (both a few dozen lines, or the entire thing).  EFL log
domains should be able to feed into these, with colours, and should be
able to split / filter bits to different areas.  Two Elm_entry's, one
not editable.  See "Entry 7" test.

IM tabs should show a very faded version of the others profile image/s.


IDEAS -

Internal window manager.
------------------------

Write my own, use ePhysics.  Hopefully ePhysics has some sort of
magnetism / attraction thingy.  See the forces demo, should be doable. 
Collision restraints and impulses?

See if Evas allows detaching stuff from one canvas and adding it to 
another canvas.  This allows things like tearing off tabs from windows,
tearing off sub menus, and switching windows between internal and
external windows, without having to entirely recreate the UI stack
within.  Hmm, think this is what swallow / unswallow is all about. 
Think that only covers stuff in the same Evas though.  Not sure this can
be done currently.  Maybe the Elm socket and plug thingy can be used? 
Some or all of the windows could be external processes anyway.  The
socket seems to be some sort of server, which can share it's content to
other plugs (processes), each one sees identical stuff, including
interactions.  The plugs can come and go as they please.  Or perhaps
elm_object_part_content_set/get/unset or
elm_object_item_part_content_set/get/unset might work for this.

An internal window has a title bar, with a centered title, and the usual
widgets.  The title part is split into three, if you grab and drag from
the middle bit, it moves as normal.  If you grab and drag from the
others, it dangles from that corner as you move it.  ePhysics magnetism
can be used for the usual "snap to nearby window" thingy.

Grabbing and flicking a window means it will move as a physics object,
bouncing off stuff until it looses enough energy to stick magnetically
to something, or lay on the bottom.

Minimised windows could be small transparent ePhysics buttons showing
just the title.  Can be dragged, flicked, or maybe double clicked to
open.  Right click for menu as usual.

Windows need title bar, close, minimize, and if they are resizable,
resize grab edges/corners, and bottom right corner resize.  Some need
menus.  They need to remember their size, position, minimized state,
closed state.  Try to put top toolbar style widgets in the title, and /
or menus.  Have the toolbar "Menu" flip down on hover.  Also add the
"tear out of window" widget for making an internal window external,
again with drag and drop or widget to bring them back in again.

All tabs should be tear off?  All menus are.  Currently menus reattach
when you close their windows.  Currently tabs re attach when you click
on their tear off button again.  Hmmm, maybe should re attach both if you
drag and drop them?  With some sort of quivering with anticipation
effect when they are in the drop zone?  Menu window can start to shrink
towards their origin menu when dragged close.  Dragging the tab button
should tear them off.  Though they currently can be dragged to re
arrange them, so that will be dragging them in the other axis then I
guess?  Tearing off should have some sort of rip and wobble effect,
maybe an ePhysics soft body?

Windows like the prim edit window should do like Elm toolbars when
resized too small, low priority widgets shrink down to a "More.."
button.

Optional hover focus on windows, maybe even on some widget types. 
Focused windows should be not quite as transparent as unfocused ones. 
Allow control over transparency levels (press on scroll wheel and wiggle it?).

Current windows use the horrid "click anywhere to focus and raise", should have an
option for proper layering.  :-P


ELM -

What is -
    Conformant?
	Squeezes things to make room for virtual keyboards and other mobile stuff.
    CTX popup?
	A pop up simple list of items.
    Mapbuf?
	Used in the launcher tests, so that might provide a clue.
	I think it just stuffs the entire container widget into a single image so that resizing and moving is faster.
	A performance tweak.
    Store (under helpers)?
	Threaded content getter for genlist, and other widgets in future.
	Basically the content of a genlist is fetched in the background, to slowly populate a genlist.
	The store can do any sort of arbitrary mapping of what it fetches to genlist item content.
	Currently this is file system based.
	Might be useful for inventory, though we really need a tree widget, which happily genlist does.
    Stored surface buffer (Launcher tests)?
	Just the mapbuf thingy above I think.



Trees.
------

From a discussion https://plus.google.com/u/0/105915569012457699790/posts/e5ZXmTQp4ig?cfem=1

By Tara Li.


"the Linden Trees are based on L-System generative techniques.  4a) Add
randomization to those L-System generations, so while the tree looks
like it's the same species, it's not the exact same specimen over and
over.  You would need a seed value that might can be locked if you do
want identical copies, but that could be transmitted with the plant so
that it looks the same for all viewers, and 4b) Add a flag so that the
Linden Plant prim includes a particle system with data defining a bark
texture, a leaf billboard texture, and the parameters of the L-systems,
so you can define your own 1-prim Linden Plants.  Include editor in the
client for Linden Plants to modify and create your own."


Contacts.
---------

Have a system of multiple sets of contacts.  The defaults will be
Everyone and Friends, each set contains an email address, and zero or
more IM addresses.  Recommend people use a spam catcher for the Everyone
contact, and don't make it mandatory.  Even the Friends one isn't
mandatory.  At all times err on the privacy side of things.

OTR
---

Since I would be adding OTR to the IM system anyway, here's a cool idea. 
Wrap all the data transfers in OTR.


The big merge
-------------

At some point, some parts of this system will become useful enough to
start merging it into Imprudence and OpenSim.  Actually, merge it into
meta-impy, that's my experimental Impy fork now, then Imprudence later. 
This discussion may not cover stuff that has not been written yet.

There's a bunch of stuff that could just run on the end of a pipe /
socket that wont need GTK / EFL integration, so I'll list those first. 
Might even be good to merge these sorts of things into meta-impy first,
it uses less of the EFL libraries, and could live on the end of a pipe,
so no need for GTK / EFL integration.

I could combine running a love server, with the libg3d work, to load
SledjHamr style sims into meta-impy.  Then morph the login screen into a
local sim in world screen.  Later could use this to allow people you
meet in OS/SL to come to your world, so long as they also have a
SledjHamr viewer (or use HG when that bit gets written).

The script library might merge into the viewer oddly enough.  I want the
viewer to be user scriptable, and LSL is a language users might be
familiar with.  Once the hybrid Lua / LSL thing is working, that's going
to be great.  Just like now, where LuaSL relies on it's client (the love
world server) to perform in world stuff, it can rely on the viewer to
perform in world stuff.  Obviously there will be some things that a
viewer can't do that an in world LSL script can, we will just have to
live with that.  Then use it as a feature of SledjHamr, which will have
no such limitation.  B-)

My AO script might work perfectly with this script engine, so I get to
include it in SledjHamr.  The love server integration mentioned above
gives this to us for free, but we can do both.

woMan is designed to be stand alone, or called out from the meta-impy
login screen.

meta-impy uses GTK2+ I think for it's library, and EFL has some sort of
GTK integration.  If I can get that to work, then the skang based stuff
can merge.  I'll list those next.

I can use the llDialog() or purkle widgets, especially when you can rip
them out of the main window to be their own windows.

Once the files widget morphs into a proper inventory widget, I can use
it in meta-impy for inventory AND an asynchronous file requester.

Finally (I think) I could rip the meta-impy graphics pipeline a new one.

Also, try to merge the script engine into OpenSim, though that might get
a lot less of a work out.  Adding server side skang to LuaSL could be
interesting.