aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries
diff options
context:
space:
mode:
authorDavid Walter Seikel2014-04-22 15:13:38 +1000
committerDavid Walter Seikel2014-04-22 15:13:38 +1000
commitdd009ccdfd62f9153dbc72f5f5de5d5f72979690 (patch)
tree50d62438c6d47dccf82f440986919b1ed3edbbd9 /libraries
parentMove most of the README's and other docs into the new docs directory. (diff)
downloadSledjHamr-dd009ccdfd62f9153dbc72f5f5de5d5f72979690.zip
SledjHamr-dd009ccdfd62f9153dbc72f5f5de5d5f72979690.tar.gz
SledjHamr-dd009ccdfd62f9153dbc72f5f5de5d5f72979690.tar.bz2
SledjHamr-dd009ccdfd62f9153dbc72f5f5de5d5f72979690.tar.xz
Move all source into the new src directory, and shuffle a few other things around.
Diffstat (limited to 'libraries')
-rw-r--r--libraries/LSL.lua870
1 files changed, 870 insertions, 0 deletions
diff --git a/libraries/LSL.lua b/libraries/LSL.lua
new file mode 100644
index 0000000..662c880
--- /dev/null
+++ b/libraries/LSL.lua
@@ -0,0 +1,870 @@
1-- A module of LSL stuffs.
2
3-- Using a module means it gets compiled each time? Maybe not if I can use bytecode files. Perhaps LuaJIT caches these?
4-- Does not seem to be slowing it down noticably, but that might change once the stubs are filled out.
5
6-- Use it like this -
7-- local _LSL = require 'LSL'
8
9--[[ From http://lua-users.org/wiki/LuaModuleFunctionCritiqued
10A related note on C code: The luaL_register [9] function in C is
11somewhat analogous to the module function in Lua, so luaL_register
12shares similar problems, at least when a non-NULL libname is used.
13Furthermore, the luaL_newmetatable/luaL_getmetatable/luaL_checkudata
14functions use a C string as a key into the global registry. This poses
15some potential for name conflicts--either because the modules were
16written by different people or because they are different versions of
17the same module loaded simultaneously. To address this, one may instead
18use a lightuserdata (pointer to variable of static linkage to ensure
19global uniqueness) for this key or store the metatable as an
20upvalue--either way is a bit more efficient and less error prone.
21]]
22
23-- http://www.lua.org/pil/15.4.html looks useful.
24-- http://www.lua.org/pil/15.5.html the last part about autoloading functions might be useful.
25
26
27local LSL = {};
28local SID = "";
29local scriptName = "";
30local running = true
31local paused = false
32local currentState = {}
33local detectedGroups = {}
34local detectedGrabs = {}
35local detectedKeys = {}
36local detectedLinkNumbers = {}
37local detectedNames = {}
38local detectedOwners = {}
39local detectedPoss = {}
40local detectedRots = {}
41local detectedTouchBinormals = {}
42local detectedTouchFaces = {}
43local detectedTouchNormals = {}
44local detectedTouchPoss = {}
45local detectedTouchSTs = {}
46local detectedTouchUVs = {}
47local detectedTypes = {}
48local detectedVels = {}
49local waitAndProcess
50
51
52-- Debugging aids
53
54-- Functions to print tables.
55local print_table, print_table_start
56
57function print_table_start(table, space, name)
58 print(space .. name .. ": ");
59 print(space .. "{");
60 print_table(table, space .. " ");
61 print(space .. "}");
62end
63
64function print_table(table, space)
65 for k, v in pairs(table) do
66 if type(v) == "table" then
67 print_table_start(v, space, k);
68 elseif type(v) == "string" then
69 print(space .. k .. ': "' .. v .. '";')
70 else
71 print(space .. k .. ": " .. v .. ";")
72 end
73 end
74end
75
76function msg(...)
77 print(SID, ...) -- The comma adds a tab, fancy that. B-)
78end
79
80
81-- Stuff called from the wire protocol has to be global, but I think this means just global to this file.
82
83events = {}
84
85function start() paused = false end
86function stop() paused = true end
87function quit() running = false end
88
89function events.detectedGroups(list) detectedGroups = list end
90function events.detectedGrabs(list) detectedGrabs = list end
91function events.detectedKeys(list) detectedKeys = list end
92function events.detectedLinkNumbers(list) detectedLinkNumbers = list end
93function events.detectedNames(list) detectedNames = list end
94function events.detectedOwners(list) detectedOwners = list end
95function events.detectedPoss(list) detectedPoss = list end
96function events.detectedRots(list) detectedRots = list end
97function events.detectedTouchBinormals(list) detectedTouchBinormals = list end
98function events.detectedTouchFaces(list) detectedTouchFaces = list end
99function events.detectedTouchNormals(list) detectedTouchNormals = list end
100function events.detectedTouchPoss(list) detectedTouchPoss = list end
101function events.detectedTouchSTs(list) detectedTouchSTs = list end
102function events.detectedTouchUVs(list) detectedTouchUVs = list end
103function events.detectedTypes(list) detectedTypes = list end
104function events.detectedVels(list) detectedVels = list end
105
106function events.detectsClear()
107 detectedGroups = {}
108 detectedGrabs = {}
109 detectedKeys = {}
110 detectedLinkNumbers = {}
111 detectedNames = {}
112 detectedOwners = {}
113 detectedPoss = {}
114 detectedRots = {}
115 detectedTouchBinormals = {}
116 detectedTouchFaces = {}
117 detectedTouchNormals = {}
118 detectedTouchPoss = {}
119 detectedTouchSTs = {}
120 detectedTouchUVs = {}
121 detectedTypes = {}
122 detectedVels = {}
123end
124
125function events.at_rot_target(tnum, targetrot, ourrot) if nil ~= currentState.at_rot_target then currentState.at_rot_target(tnum, targetrot, ourrot) end events.detectsClear() end
126function events.at_target(tnum, targetpos, ourpos) if nil ~= currentState.at_target then currentState.at_target(tnum, targetpos, ourpos) end events.detectsClear() end
127function events.attach(id) if nil ~= currentState.attach then currentState.attach(id) end events.detectsClear() end
128function events.changed(change) if nil ~= currentState.changed then currentState.changed(change) end events.detectsClear() end
129function events.collision_start(num_detected) if nil ~= currentState.collision_start then currentState.collision_start(num_detected) end events.detectsClear() end
130function events.collision(num_detected) if nil ~= currentState.collision then currentState.collision(num_detected) end events.detectsClear() end
131function events.collision_end(num_detected) if nil ~= currentState.collision_end then currentState.collision_end(num_detected) end events.detectsClear() end
132function events.control(id, held, changed) if nil ~= currentState.control then currentState.control(id, held, changed) end events.detectsClear() end
133function events.dataserver(queryid, data) if nil ~= currentState.dataserver then currentState.dataserver(queryid, data) end events.detectsClear() end
134function events.email(Time, address, subj, message, num_left) if nil ~= currentState.email then currentState.email(Time, address, subj, message, num_left) end events.detectsClear() end
135function events.http_request(request_id, status, metadata, body) if nil ~= currentState.http_request then currentState.http_request(request_id, status, metadata, body) end events.detectsClear() end
136function events.http_response(request_id, status, metadata, body) if nil ~= currentState.http_response then currentState.http_response(request_id, status, metadata, body) end events.detectsClear() end
137function events.land_collision_start(pos) if nil ~= currentState.land_collision_start then currentState.land_collision_start(pos) end events.detectsClear() end
138function events.land_collision(pos) if nil ~= currentState.land_collision then currentState.land_collision(pos) end events.detectsClear() end
139function events.land_collision_end(pos) if nil ~= currentState.land_collision_end then currentState.land_collision_end(pos) end events.detectsClear() end
140function events.link_message(sender_num, num, str, id) if nil ~= currentState.link_message then currentState.link_message(sender_num, num, str, id) end events.detectsClear() end
141function events.listen(channel, name, id, message) if nil ~= currentState.listen then currentState.listen(channel, name, id, message) end events.detectsClear() end
142function events.money(id, amount) if nil ~= currentState.money then currentState.money(id, amount) end events.detectsClear() end
143function events.moving_start() if nil ~= currentState.moving_start then currentState.moving_start() end events.detectsClear() end
144function events.moving_end() if nil ~= currentState.moving_end then currentState.moving_end() end events.detectsClear() end
145function events.no_sensor() if nil ~= currentState.no_sensor then currentState.no_sensor() end events.detectsClear() end
146function events.not_at_rot_target() if nil ~= currentState.not_at_rot_target then currentState.not_at_rot_target() end events.detectsClear() end
147function events.not_at_target() if nil ~= currentState.not_at_target then currentState.not_at_target() end events.detectsClear() end
148function events.object_rez(id) if nil ~= currentState.object_rez then currentState.object_rez() end events.detectsClear() end
149function events.on_rez(start_param) if nil ~= currentState.on_rezz then currentState.on_rez(start_param) end events.detectsClear() end
150function events.remote_data(event_type, channel, message_id, sender, idata, sdata) if nil ~= currentState.remote_data then currentState.remote_data(event_type, channel, message_id, sender, idata, sdata) end events.detectsClear() end
151function events.run_time_permissions(perm) if nil ~= currentState.run_time_permisions then currentState.run_time_permissions(perm) end events.detectsClear() end
152function events.sensor(num_detected) if nil ~= currentState.sensor then currentState.sensor(num_detected) end events.detectsClear() end
153function events.state_entry() if nil ~= currentState.state_entry then currentState.state_entry() end events.detectsClear() end
154function events.state_exit() if nil ~= currentState.state_exit then currentState.state_exit() end events.detectsClear() end
155function events.timer() if nil ~= currentState.timer then currentState.timer() end events.detectsClear() end
156function events.touch_start(num_detected) if nil ~= currentState.touch_start then currentState.touch_start(num_detected) end events.detectsClear() end
157function events.touch(num_detected) if nil ~= currentState.touch then currentState.touch(num_detected) end events.detectsClear() end
158function events.touch_end(num_detected) if nil ~= currentState.touch_end then currentState.touch_end(num_detected) end events.detectsClear() end
159function events.transaction_result(id, success, data) if nil ~= currentState.transaction_result then currentState.transaction_result(id, success, data) end events.detectsClear() end
160
161
162-- LSL function and constant creation stuff.
163
164local args2string -- Pre declare this.
165local functions = {}
166local mt = {}
167
168local function value2string(value, Type)
169 local temp = ""
170
171 if "float" == Type then temp = temp .. value
172 elseif "integer" == Type then temp = temp .. value
173 elseif "key" == Type then temp = "\"" .. value .. "\""
174 elseif "list" == Type then temp = "[" .. args2string(true, unpack(value)) .. "]"
175 elseif "table" == Type then temp = "[" .. args2string(true, unpack(value)) .. "]"
176 elseif "string" == Type then temp = "\"" .. value .. "\""
177 elseif "rotation" == Type then temp = "<" .. value.x .. ", " .. value.y .. ", " .. value.z .. ", " .. value.s .. ">"
178 elseif "vector" == Type then temp = "<" .. value.x .. ", " .. value.y .. ", " .. value.z .. ">"
179 else
180 temp = temp .. value
181 end
182 return temp
183end
184
185function args2string(doType, ...)
186 local temp = ""
187 local first = true
188
189 for j,w in ipairs( {...} ) do
190 if first then first = false else temp = temp .. ", " end
191 if doType then
192 temp = temp .. value2string(w, type(w))
193 else
194 temp = temp .. w
195 end
196 end
197 return temp
198end
199
200function mt.callAndReturn(name, ...)
201 luaproc.sendback(name .. "(" .. args2string(true, ...) .. ")")
202end
203
204function mt.callAndWait(name, ...)
205 mt.callAndReturn(name, ...);
206 -- Eventually a sendForth() is called, which should end up passing through SendToChannel().
207 -- Wait for the result, which should be a Lua value as a string.
208 return waitAndProcess(true)
209end
210
211local function newConst(Type, name, value)
212 LSL[name] = value
213 return { Type = Type, name = name }
214end
215
216local function newFunc(Type, name, ... )
217 functions[name] = { Type = Type, args = {...} }
218 if "" == Type then
219 LSL[name] = function(...) mt.callAndReturn(name, ... ) end
220 else
221 LSL[name] = function(...) return mt.callAndWait(name, ... ) end
222 end
223end
224
225
226-- LSL constants.
227
228local constants =
229{
230 newConst("float", "PI", 3.14159265358979323846264338327950),
231 newConst("float", "PI_BY_TWO", LSL.PI / 2), -- 1.57079632679489661923132169163975
232 newConst("float", "TWO_PI", LSL.PI * 2), -- 6.28318530717958647692528676655900
233 newConst("float", "DEG_TO_RAD", LSL.PI / 180.0), -- 0.01745329252
234 newConst("float", "RAD_TO_DEG", 180.0 / LSL.PI), -- 57.2957795131
235 newConst("float", "SQRT2", 1.4142135623730950488016887242097),
236
237 newConst("integer", "CHANGED_INVENTORY", 0x001),
238 newConst("integer", "CHANGED_COLOR", 0x002),
239 newConst("integer", "CHANGED_SHAPE", 0x004),
240 newConst("integer", "CHANGED_SCALE", 0x008),
241 newConst("integer", "CHANGED_TEXTURE", 0x010),
242 newConst("integer", "CHANGED_LINK", 0x020),
243 newConst("integer", "CHANGED_ALLOWED_DROP", 0x040),
244 newConst("integer", "CHANGED_OWNER", 0x080),
245 newConst("integer", "CHANGED_REGION", 0x100),
246 newConst("integer", "CHANGED_TELEPORT", 0x200),
247 newConst("integer", "CHANGED_REGION_START", 0x400),
248 newConst("integer", "CHANGED_MEDIA", 0x800),
249
250 newConst("integer", "DEBUG_CHANNEL", 2147483647),
251 newConst("integer", "PUBLIC_CHANNEL", 0),
252
253 newConst("integer", "INVENTORY_ALL", -1),
254 newConst("integer", "INVENTORY_NONE", -1),
255 newConst("integer", "INVENTORY_TEXTURE", 0),
256 newConst("integer", "INVENTORY_SOUND", 1),
257 newConst("integer", "INVENTORY_LANDMARK", 3),
258 newConst("integer", "INVENTORY_CLOTHING", 5),
259 newConst("integer", "INVENTORY_OBJECT", 6),
260 newConst("integer", "INVENTORY_NOTECARD", 7),
261 newConst("integer", "INVENTORY_SCRIPT", 10),
262 newConst("integer", "INVENTORY_BODYPART", 13),
263 newConst("integer", "INVENTORY_ANIMATION", 20),
264 newConst("integer", "INVENTORY_GESTURE", 21),
265
266 newConst("integer", "ALL_SIDES", -1),
267 newConst("integer", "LINK_SET", -1),
268 newConst("integer", "LINK_ROOT", 1),
269 newConst("integer", "LINK_ALL_OTHERS", -2),
270 newConst("integer", "LINK_ALL_CHILDREN", -3),
271 newConst("integer", "LINK_THIS", -4),
272
273 newConst("integer", "PERM_ALL", 0x7FFFFFFF),
274 newConst("integer", "PERM_COPY", 0x00008000),
275 newConst("integer", "PERM_MODIFY", 0x00004000),
276 newConst("integer", "PERM_MOVE", 0x00080000),
277 newConst("integer", "PERM_TRANSFER", 0x00002000),
278 newConst("integer", "MASK_BASE", 0),
279 newConst("integer", "MASK_OWNER", 1),
280 newConst("integer", "MASK_GROUP", 2),
281 newConst("integer", "MASK_EVERYONE", 3),
282 newConst("integer", "MASK_NEXT", 4),
283 newConst("integer", "PERMISSION_DEBIT", 0x0002),
284 newConst("integer", "PERMISSION_TAKE_CONTROLS", 0x0004),
285 newConst("integer", "PERMISSION_TRIGGER_ANIMATION", 0x0010),
286 newConst("integer", "PERMISSION_ATTACH", 0x0020),
287 newConst("integer", "PERMISSION_CHANGE_LINKS", 0x0080),
288 newConst("integer", "PERMISSION_TRACK_CAMERA", 0x0400),
289 newConst("integer", "PERMISSION_CONTRAL_CAMERA", 0x0800),
290
291 newConst("integer", "AGENT", 0x01),
292 newConst("integer", "ACTIVE", 0x02),
293 newConst("integer", "PASSIVE", 0x04),
294 newConst("integer", "SCRIPTED", 0x08),
295
296 newConst("integer", "OBJECT_UNKNOWN_DETAIL", -1),
297
298 newConst("integer", "PRIM_BUMP_SHINY", 19),
299 newConst("integer", "PRIM_COLOR", 18),
300 newConst("integer", "PRIM_FLEXIBLE", 21),
301 newConst("integer", "PRIM_FULLBRIGHT", 20),
302 newConst("integer", "PRIM_GLOW", 25),
303 newConst("integer", "PRIM_MATERIAL", 2),
304 newConst("integer", "PRIM_PHANTOM", 5),
305 newConst("integer", "PRIM_PHYSICS", 3),
306 newConst("integer", "PRIM_POINT_LIGHT", 23),
307 newConst("integer", "PRIM_POSITION", 6),
308 newConst("integer", "PRIM_ROTATION", 8),
309 newConst("integer", "PRIM_SIZE", 7),
310 newConst("integer", "PRIM_TEMP_ON_REZ", 4),
311 newConst("integer", "PRIM_TYPE", 9),
312 newConst("integer", "PRIM_TYPE_OLD", 1),
313 newConst("integer", "PRIM_TEXGEN", 22),
314 newConst("integer", "PRIM_TEXTURE", 17),
315 newConst("integer", "PRIM_TEXT", 26),
316
317 newConst("integer", "PRIM_BUMP_NONE", 0),
318 newConst("integer", "PRIM_BUMP_BRIGHT", 1),
319 newConst("integer", "PRIM_BUMP_DARK", 2),
320 newConst("integer", "PRIM_BUMP_WOOD", 3),
321 newConst("integer", "PRIM_BUMP_BARK", 4),
322 newConst("integer", "PRIM_BUMP_BRICKS", 5),
323 newConst("integer", "PRIM_BUMP_CHECKER", 6),
324 newConst("integer", "PRIM_BUMP_CONCRETE", 7),
325 newConst("integer", "PRIM_BUMP_TILE", 8),
326 newConst("integer", "PRIM_BUMP_STONE", 9),
327 newConst("integer", "PRIM_BUMP_DISKS", 10),
328 newConst("integer", "PRIM_BUMP_GRAVEL", 11),
329 newConst("integer", "PRIM_BUMP_BLOBS", 12),
330 newConst("integer", "PRIM_BUMP_SIDING", 13),
331 newConst("integer", "PRIM_BUMP_LARGETILE", 14),
332 newConst("integer", "PRIM_BUMP_STUCCO", 15),
333 newConst("integer", "PRIM_BUMP_SUCTION", 16),
334 newConst("integer", "PRIM_BUMP_WEAVE", 17),
335
336 newConst("integer", "PRIM_HOLE_DEFAULT", 0),
337 newConst("integer", "PRIM_HOLE_CIRCLE", 16),
338 newConst("integer", "PRIM_HOLE_SQUARE", 32),
339 newConst("integer", "PRIM_HOLE_TRIANGLE", 48),
340
341 newConst("integer", "PRIM_MATERIAL_STONE", 0),
342 newConst("integer", "PRIM_MATERIAL_METAL", 1),
343 newConst("integer", "PRIM_MATERIAL_GLASS", 2),
344 newConst("integer", "PRIM_MATERIAL_WOOD", 3),
345 newConst("integer", "PRIM_MATERIAL_FLESH", 4),
346 newConst("integer", "PRIM_MATERIAL_PLASTIC", 5),
347 newConst("integer", "PRIM_MATERIAL_RUBBER", 6),
348 newConst("integer", "PRIM_MATERIAL_LIGHT", 7),
349
350 newConst("integer", "PRIM_SCULPT_TYPE_SPHERE", 1),
351 newConst("integer", "PRIM_SCULPT_TYPE_TORUS", 2),
352 newConst("integer", "PRIM_SCULPT_TYPE_PLANE", 3),
353 newConst("integer", "PRIM_SCULPT_TYPE_CYLINDER", 4),
354 newConst("integer", "PRIM_SCULPT_TYPE_MESH", 5),
355 newConst("integer", "PRIM_SCULPT_TYPE_MIMESH", 6),
356
357 newConst("integer", "PRIM_SHINY_NONE", 0),
358 newConst("integer", "PRIM_SHINY_LOW", 1),
359 newConst("integer", "PRIM_SHINY_MEDIUM", 2),
360 newConst("integer", "PRIM_SHINY_HIGH", 3),
361
362 newConst("integer", "PRIM_TYPE_BOX", 0),
363 newConst("integer", "PRIM_TYPE_CYLINDER", 1),
364 newConst("integer", "PRIM_TYPE_PRISM", 2),
365 newConst("integer", "PRIM_TYPE_SPHERE", 3),
366 newConst("integer", "PRIM_TYPE_TORUS", 4),
367 newConst("integer", "PRIM_TYPE_TUBE", 5),
368 newConst("integer", "PRIM_TYPE_RING", 6),
369 newConst("integer", "PRIM_TYPE_SCULPT", 7),
370
371 newConst("integer", "STRING_TRIM", 3),
372 newConst("integer", "STRING_TRIM_HEAD", 1),
373 newConst("integer", "STRING_TRIM_TAIL", 2),
374
375 newConst("integer", "TRUE", 1),
376 newConst("integer", "FALSE", 0),
377
378 newConst("integer", "TOUCH_INVALID_FACE", 0x7FFFFFFF),
379 newConst("vector", "TOUCH_INVALID_TEXCOORD", {x=-1.0, y=-1.0, z=0.0}),
380 newConst("vector", "TOUCH_INVALID_VECTOR", {x=0.0, y=0.0, z=0.0}),
381
382 newConst("integer", "TYPE_INTEGER", 1),
383 newConst("integer", "TYPE_FLOAT", 2),
384 newConst("integer", "TYPE_STRING", 3),
385 newConst("integer", "TYPE_KEY", 4),
386 newConst("integer", "TYPE_VECTOR", 5),
387 newConst("integer", "TYPE_ROTATION", 6),
388 newConst("integer", "TYPE_INVALID", 0),
389
390 newConst("string", "NULL_KEY", "00000000-0000-0000-0000-000000000000"),
391 newConst("string", "EOF", "\\n\\n\\n"), -- Corner case, dealt with later.
392
393 newConst("rotation", "ZERO_ROTATION", {x=0.0, y=0.0, z=0.0, s=1.0}),
394 newConst("vector", "ZERO_VECTOR", {x=0.0, y=0.0, z=0.0}),
395
396-- TODO - Temporary dummy variables to get vector and rotation thingies to work for now.
397
398 newConst("float", "s", 1.0),
399 newConst("float", "x", 0.0),
400 newConst("float", "y", 0.0),
401 newConst("float", "z", 0.0),
402}
403
404-- ll*() function definitions
405
406-- LSL avatar functions
407newFunc("key", "llAvatarOnSitTarget")
408newFunc("list", "llGetAnimationList", "key id")
409newFunc("integer", "llGetPermissions")
410newFunc("key", "llGetPermissionsKey")
411newFunc("string", "llKey2Name", "key avatar")
412newFunc("", "llRequestPermissions", "key avatar", "integer perms")
413newFunc("integer", "llSameGroup", "key avatar")
414newFunc("", "llStartAnimation", "string anim")
415newFunc("", "llStopAnimation", "string anim")
416newFunc("", "llUnSit", "key avatar")
417
418-- LSL collision / detect / sensor functions
419newFunc("integer", "llDetectedGroup", "integer index")
420newFunc("vector", "llDetectedGrab", "integer index")
421newFunc("key", "llDetectedKey", "integer index")
422newFunc("integer", "llDetectedLinkNumber", "integer index")
423newFunc("string", "llDetectedName", "integer index")
424newFunc("key", "llDetectedOwner", "integer index")
425newFunc("vector", "llDetectedPos", "integer index")
426newFunc("rotation", "llDetectedRot", "integer index")
427newFunc("vector", "llDetectedTouchBinormal", "integer index")
428newFunc("integer", "llDetectedTouchFace", "integer index")
429newFunc("vector", "llDetectedTouchNormal", "integer index")
430newFunc("vector", "llDetectedTouchPos", "integer index")
431newFunc("vector", "llDetectedTouchST", "integer index")
432newFunc("vector", "llDetectedTouchUV", "integer index")
433newFunc("integer", "llDetectedType", "integer index")
434newFunc("vector", "llDetectedVel", "integer index")
435
436
437-- LSL communications functions
438newFunc("", "llDialog", "key avatar", "string caption", "list arseBackwardsMenu", "integer channel")
439newFunc("integer", "llListen", "integer channel", "string name", "key id", "string msg")
440newFunc("", "llListenRemove", "integer handle")
441newFunc("", "llOwnerSay", "string text")
442newFunc("", "llSay", "integer channel", "string text")
443newFunc("", "llShout", "integer channel", "string text")
444newFunc("", "llWhisper", "integer channel", "string text")
445newFunc("", "llMessageLinked", "integer link", "integer num", "string text", "key aKey")
446
447-- LSL inventory functions.
448newFunc("string", "llGetInventoryName", "integer Type", "integer index")
449newFunc("integer", "llGetInventoryNumber", "integer Type")
450newFunc("integer", "llGetInventoryType", "string name")
451newFunc("key", "llGetNotecardLine", "string name", "integer index")
452newFunc("", "llRezAtRoot", "string name", "vector position", "vector velocity", "rotation rot", "integer channel")
453newFunc("", "llRezObject", "string name", "vector position", "vector velocity", "rotation rot", "integer channel")
454
455-- LSL list functions.
456newFunc("list", "llCSV2List", "string text")
457newFunc("list", "llDeleteSubList", "list l", "integer start", "integer End")
458newFunc("string", "llDumpList2String", "list l", "string separator")
459newFunc("integer", "llGetListLength", "list l")
460newFunc("string", "llList2CSV", "list l")
461newFunc("float", "llList2Float", "list l", "integer index")
462newFunc("integer", "llList2Integer", "list l", "integer index")
463newFunc("key", "llList2Key", "list l", "integer index")
464newFunc("list", "llList2List", "list l", "integer start", "integer End")
465newFunc("string", "llList2String", "list l", "integer index")
466newFunc("rotation", "llList2Rotation", "list l", "integer index")
467newFunc("vector", "llList2Vector", "list l", "integer index")
468newFunc("integer", "llListFindList", "list l", "list l1")
469newFunc("list", "llListInsertList", "list l", "list l1", "integer index")
470newFunc("list", "llListReplaceList", "list l", "list part", "integer start", "integer End")
471newFunc("list", "llListSort", "list l", "integer stride", "integer ascending")
472newFunc("list", "llParseString2List", "string In", "list l", "list l1")
473newFunc("list", "llParseStringKeepNulls", "string In", "list l", "list l1")
474
475-- LSL math functions
476newFunc("rotation", "llEuler2Rot", "vector vec")
477newFunc("float", "llFrand", "float max")
478newFunc("float", "llPow", "float number", "float places")
479newFunc("vector", "llRot2Euler", "rotation rot")
480newFunc("integer", "llRound", "float number")
481
482-- LSL media functions
483newFunc("", "llPlaySound", "string name", "float volume")
484
485-- LSL object / prim functions
486newFunc("", "llDie")
487newFunc("key", "llGetKey")
488newFunc("integer", "llGetLinkNumber")
489newFunc("string", "llGetObjectDesc")
490newFunc("string", "llGetObjectName")
491newFunc("key", "llGetOwner")
492newFunc("", "llSetObjectDesc", "string text")
493newFunc("", "llSetObjectName", "string text")
494newFunc("", "llSetPrimitiveParams", "list params")
495newFunc("", "llSetSitText", "string text")
496newFunc("", "llSetText", "string text", "vector colour", "float alpha")
497newFunc("", "llSitTarget", "vector pos", "rotation rot")
498
499-- LSL rotation / scaling / translation functions
500newFunc("vector", "llGetPos")
501newFunc("rotation", "llGetRot")
502newFunc("", "llSetPos", "vector pos")
503newFunc("", "llSetRot", "rotation rot")
504newFunc("", "llSetScale", "vector scale")
505
506-- LSL script functions
507newFunc("integer", "llGetFreeMemory")
508newFunc("string", "llGetScriptName")
509newFunc("", "llResetOtherScript", "string name")
510newFunc("", "llResetScript")
511newFunc("", "llSetScriptState", "string name", "integer running")
512
513-- LSL string functions
514newFunc("string", "llGetSubString", "string text", "integer start", "integer End")
515newFunc("integer", "llStringLength", "string text")
516newFunc("string", "llStringTrim", "string text", "integer type")
517newFunc("integer", "llSubStringIndex", "string text", "string sub")
518
519-- LSL texture functions
520newFunc("float", "llGetAlpha", "integer side")
521newFunc("", "llSetAlpha", "float alpha", "integer side")
522newFunc("", "llSetColor", "vector colour", "integer side")
523
524-- LSL time functions
525newFunc("float", "llGetTime")
526newFunc("", "llResetTime")
527newFunc("", "llSetTimerEvent", "float seconds")
528newFunc("float", "llSleep", "float seconds") -- Faked return type, it actually does not return anything. This forces it to wait. Actually fully implements llSleep(). B-)
529
530
531-- TODO - fake this for now.
532function --[[integer]] LSL.llGetInventoryType(--[[string]] name) return LSL.INVENTORY_SCRIPT end;
533
534
535-- LSL collision / detect / sensor functions
536function --[[integer]] LSL.llDetectedGroup( --[[integer]] index) return detectedGroups [index + 1] or false end
537function --[[vector]] LSL.llDetectedGrab( --[[integer]] index) return detectedGrabs [index + 1] or LSL.ZERO_VECTOR end
538function --[[key]] LSL.llDetectedKey( --[[integer]] index) return detectedKeys [index + 1] or LSL.NULL_KEY end -- LL says "returns empty key" which is "", but LSL Wiki says NULL_KEY
539function --[[integer]] LSL.llDetectedLinkNumber( --[[integer]] index) return detectedLinkNumbers [index + 1] or 0 end
540function --[[string]] LSL.llDetectedName( --[[integer]] index) return detectedNames [index + 1] or "" end -- LL says it returns NULL_KEY, LSL Wiki says an empty string. Apparently there used to be an exploit for creating multi kb names, normally they are 255 characters.
541function --[[key]] LSL.llDetectedOwner( --[[integer]] index) return detectedOwners [index + 1] or LSL.NULL_KEY end -- LL says "returns empty key" which is "", but LSL Wiki says NULL_KEY
542function --[[vector]] LSL.llDetectedPos( --[[integer]] index) return detectedPoss [index + 1] or LSL.ZERO_VECTOR end
543function --[[rotation]] LSL.llDetectedRot( --[[integer]] index) return detectedRots [index + 1] or LSL.ZERO_ROTATION end
544function --[[vector]] LSL.llDetectedTouchBinormal( --[[integer]] index) return detectedTouchBinormals [index + 1] or LSL.TOUCH_INVALID_VECTOR end
545function --[[integer]] LSL.llDetectedTouchFace( --[[integer]] index) return detectedTouchFaces [index + 1] or LSL.TOUCH_INVALID_FACE end
546function --[[vector]] LSL.llDetectedTouchNormal( --[[integer]] index) return detectedTouchNormals [index + 1] or LSL.TOUCH_INVALID_VECTOR end
547function --[[vector]] LSL.llDetectedTouchPos( --[[integer]] index) return detectedTouchPoss [index + 1] or LSL.TOUCH_INVALID_VECTOR end
548function --[[vector]] LSL.llDetectedTouchST( --[[integer]] index) return detectedTouchSTs [index + 1] or LSL.TOUCH_INVALID_TEXCOORD end
549function --[[vector]] LSL.llDetectedTouchUV( --[[integer]] index) return detectedTouchUVs [index + 1] or LSL.TOUCH_INVALID_TEXCOORD end
550function --[[integer]] LSL.llDetectedType( --[[integer]] index) return detectedTypes [index + 1] or 0 end
551function --[[vector]] LSL.llDetectedVel( --[[integer]] index) return detectedVels [index + 1] or LSL.ZERO_VECTOR end
552
553
554-- LSL list functions.
555
556--function --[[list]] LSL.llCSV2List(--[[string]] text) return {} end;
557function --[[list]] LSL.llDeleteSubList(--[[list]] l,--[[integer]] start,--[[integer]] eNd)
558 local result = {}
559 local x = 1
560
561 -- Deal with the impedance mismatch.
562 start = start + 1
563 eNd = eNd + 1
564 for i = 1,#l do
565 if i < start then result[x] = l[i]; x = x + 1
566 elseif i > eNd then result[x] = l[i]; x = x + 1
567 end
568 end
569
570 return result
571end
572
573function --[[string]] LSL.llDumpList2String(--[[list]] l, --[[string]] separator)
574 local result = ""
575 for i = 1,#l do
576 if "" ~= result then result = result .. separator end
577 result = result .. l[i]
578 end
579 return result
580end
581
582function --[[integer]] LSL.llGetListLength(--[[list]] l)
583 return #l
584end
585
586function --[[string]] LSL.llList2CSV(--[[list]] l)
587 return LSL.llDumpList2String(l, ",")
588end
589
590function --[[float]] LSL.llList2Float(--[[list]] l,--[[integer]] index)
591 local result = tonumber(l[index])
592 if nil == result then result = 0.0 end
593 return result
594end
595
596function --[[integer]] LSL.llList2Integer(--[[list]] l,--[[integer]] index)
597 local result = tonumber(l[index+1])
598 if nil == result then result = 0 end
599 return result
600end
601
602function --[[key]] LSL.llList2Key(--[[list]] l,--[[integer]] index)
603 local result = l[index+1]
604 if result then return "" .. result else return LSL.NULL_KEY end
605end
606
607function --[[list]] LSL.llList2List(--[[list]] l,--[[integer]] start,--[[integer]] eNd)
608 local result = {}
609 local x = 1
610
611 --[[ TODO -
612Using negative numbers for start and/or end causes the index to count backwards from the length of the list, so 0, -1 would capture the entire list.
613If start is larger than end the list returned is the exclusion of the entries, so 6, 4 would give the entire list except for the 5th entry.
614 ]]
615
616 -- Deal with the impedance mismatch.
617 start = start + 1
618 eNd = eNd + 1
619 for i = 1,#l do
620 if i >= start then result[x] = l[i]; x = x + 1
621 elseif i <= eNd then result[x] = l[i]; x = x + 1
622 end
623 end
624
625 return result
626end
627
628function --[[string]] LSL.llList2String(--[[list]] l,--[[integer]] index)
629 local result = l[index+1]
630 if result then return "" .. result else return "" end
631end
632
633function --[[rotation]] LSL.llList2Rotation(--[[list]] l,--[[integer]] index)
634 local result = l[index+1]
635 if nil == result then result = LSL.ZERO_ROTATION end
636 -- TODO - check if it's not an actual rotation, then return LSS.ZERO_ROTATION
637 return result
638end
639
640function --[[vector]] LSL.llList2Vector(--[[list]] l,--[[integer]] index)
641 local result = l[index+1]
642 if nil == result then result = LSL.ZERO_VECTOR end
643 -- TODO - check if it's not an actual rotation, then return LSS.ZERO_VECTOR
644 return result
645end
646
647--function --[[integer]] LSL.llListFindList(--[[list]] l, --[[list]] l1) return 0 end;
648function --[[list]] LSL.llListInsertList(--[[list]] l, --[[list]] l1,--[[integer]] index)
649 local result = {}
650 local x = 1
651 local y
652 for i = 1,index do
653 result[x] = l[i]
654 x = x + 1
655 end
656 y = x
657 for i = 1,#ll do
658 result[x] = ll[i]
659 x = x + 1
660 end
661 for i = y,#l do
662 result[x] = l[i]
663 x = x + 1
664 end
665 return result
666end
667
668function --[[list]] LSL.llListReplaceList(--[[list]] l, --[[list]] part,--[[integer]] start,--[[integer]] eNd)
669 local result = {}
670 local x = 1
671 local y
672 for i = 1,index do
673 result[x] = l[i]
674 x = x + 1
675 end
676 for i = 1,#part do
677 result[x] = part[i]
678 x = x + 1
679 end
680 for i = index,#l do
681 result[x] = l[i]
682 x = x + 1
683 end
684 return result
685end
686
687function --[[list]] LSL.llListSort(--[[list]] l,--[[integer]] stride,--[[integer]] ascending)
688 local result = {}
689
690 -- TODO - Deal with stride and ascending.
691 for i = 1,#l do
692 result[x] = l[i]; x = x + 1
693 end
694 table.sort(result)
695
696 return result
697end
698
699--function --[[list]] LSL.llParseString2List(--[[string]] In, --[[list]] l, --[[list]] l1) return {} end;
700--function --[[list]] LSL.llParseStringKeepNulls(--[[string]] In, --[[list]] l, --[[list]] l1) return {} end;
701
702
703-- LSL script functions
704
705function --[[string]] LSL.llGetScriptName()
706 return scriptName
707end
708
709
710-- LSL string functions
711
712function --[[string]] LSL.llGetSubString(--[[string]] text, --[[integer]] start, --[[integer]] End)
713 -- Deal with the impedance mismatch.
714 if 0 <= start then start = start + 1 end
715 if 0 <= End then End = End + 1 end
716-- TODO - If start is larger than end the substring is the exclusion of the entries, so 6,4 would give the entire string except for the 5th character.
717 return string.sub(text, start, End)
718end
719
720function --[[integer]] LSL.llSubStringIndex(--[[string]] text, --[[string]] sub)
721 local start, End = string.find(text, sub, 1, true)
722
723 if nil == start then return -1 else return start - 1 end
724end
725
726
727-- Crements stuff.
728
729function LSL.preDecrement(name) _G[name] = _G[name] - 1; return _G[name]; end;
730function LSL.preIncrement(name) _G[name] = _G[name] + 1; return _G[name]; end;
731function LSL.postDecrement(name) local temp = _G[name]; _G[name] = _G[name] - 1; return temp; end;
732function LSL.postIncrement(name) local temp = _G[name]; _G[name] = _G[name] + 1; return temp; end;
733
734
735-- State stuff
736
737function LSL.stateChange(x)
738 if currentState ~= x then -- Changing to the same state is a NOP.
739 -- TODO - Should clear out pending events, except timer()
740 -- Also forget about any event setup that needs setting up via some ll*() function, except timer().
741 if nil ~= currentState.state_exit then
742 currentState.state_exit();
743 end
744 currentState = x;
745 --[[ Never return to the current states event handler. In theory. lol
746 Notably, it's not actually legal to do a state change from a function, only from handlers.
747 There is a hack though, but it's unsupported, so I don't have to worry about it so much.
748
749 Write out "state new;" as "return _LSL.stateChange(newState);", with stateChange() returning new.state_entry()) which will force two tail calls.
750
751 The caller of stateChange() might be a function rather than an event handler.
752 Which will return to the event handler (possibly via other nested function calls) as if the state never changed.
753 http://lslwiki.net/lslwiki/wakka.php?wakka=FunctionStateChangeHack seems to imply that this is exactly what LSL does.
754 Soooo, this might actually work perfectly.
755 Except for one minor quirk, as that page shows - only the top level function's state sticks, unless the handler does one to, then the handlers one overrides things.
756 Which I can probably ignore anyway, as this entire calling states within functions thing is an unsupported hack.
757 ]]
758 if nil ~= currentState.state_entry then
759 return currentState.state_entry();
760 end
761 end
762end;
763
764function LSL.mainLoop(sid, name, x)
765 local status, errorMsg
766 local result
767
768 SID = sid
769 scriptName = name
770 LSL.EOF = "\n\n\n" -- Fix this up now.
771
772 LSL.stateChange(x);
773 waitAndProcess(false)
774 msg("Script quitting.")
775end
776
777function waitAndProcess(returnWanted)
778 local Type = "event"
779
780 if returnWanted then Type = "result" end
781 while running do
782 local message = luaproc.receive(SID)
783 if message then
784 -- TODO - should we be discarding return values while paused? I don't think so, so we need to process those,
785 if paused then
786 if "start()" == message then paused = false end
787 else
788 result, errorMsg = loadstring(message) -- "The environment of the returned function is the global environment." Though normally, a function inherits it's environment from the function creating it. Which is what we want. lol
789 if nil == result then
790 msg("Not a valid " .. Type .. ": " .. message .. " ERROR MESSAGE: " .. errorMsg)
791 else
792 -- Set the functions environment to ours, for the protection of the script, coz loadstring sets it to the global environment instead.
793 -- TODO - On the other hand, we will need the global environment when we call event handlers. So we should probably stash it around here somewhere.
794 -- Meh, seems to be working fine as it is.
795 setfenv(result, getfenv(1))
796 status, result = pcall(result)
797 if not status then
798 msg("Error from " .. Type .. ": " .. message .. " ERROR MESSAGE: " .. result)
799 elseif result then
800 -- Check if we are waiting for a return, and got it.
801 if returnWanted and string.match(message, "^return ") then
802 return result
803 end
804 -- Otherwise, just run it and keep looping.
805 status, errorMsg = luaproc.send(sid, result)
806 if not status then
807 msg("Error sending results from " .. Type .. ": " .. message .. " ERROR MESSAGE: " .. errorMsg)
808 end
809 end
810 end
811 end
812 end
813 end
814end
815
816-- Typecasting stuff.
817
818function LSL.floatTypecast(x)
819 local temp = tonumber(x)
820 if nil == temp then temp = 0 end
821 return temp;
822end
823
824function LSL.integerTypecast(x)
825 local temp = tonumber(x)
826 if nil == temp then temp = 0 end
827 return temp;
828end
829
830function LSL.keyTypecast(x)
831 return "" .. x;
832end
833
834function LSL.listTypecast(x)
835 return {x};
836end
837
838function LSL.rotationTypecast(x)
839 return x;
840end
841
842function LSL.stringTypecast(x)
843 return "" .. x;
844end
845
846function LSL.vectorTypecast(x)
847 return x;
848end
849
850
851-- Called at compiler set up time, to produce the constants.lsl file.
852function LSL.gimmeLSL()
853 for i,v in ipairs(constants) do
854 local value = LSL[v.name]
855
856 print(v.Type .. " " .. v.name .. " = " .. value2string(value, v.Type) .. ";")
857 end
858
859 for k in pairs(functions) do
860 local v = functions[k]
861 if nil == v.args then
862 print(v.Type .. " " .. k .. "(){}")
863 else
864 print(v.Type .. " " .. k .. "(" .. args2string(false, unpack(v.args)) .. "){}")
865 end
866 end
867end
868
869
870return LSL;