mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 07:38:21 +00:00
315 lines
9.1 KiB
Python
315 lines
9.1 KiB
Python
# (C) Copyright 2015-2018 Sei Lisa. All rights reserved.
|
|
#
|
|
# This file is part of LSL PyOptimizer.
|
|
#
|
|
# LSL PyOptimizer is free software: you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# LSL PyOptimizer is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with LSL PyOptimizer. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# Extra functions that have predictable return values for certain arguments.
|
|
|
|
from lslcommon import Key, Vector #, Quaternion
|
|
from lslbasefuncs import ELSLCantCompute, fi,ff,fs,fk,v2f,q2f,fl, \
|
|
NULL_KEY, ZERO_VECTOR, ZERO_ROTATION, \
|
|
TOUCH_INVALID_TEXCOORD, cond
|
|
ff, q2f # keep pyflakes happy as these are not used
|
|
|
|
GetEnvSettings = frozenset(('agent_limit', 'dynamic_pathfinding', 'estate_id',
|
|
'estate_name', 'frame_number', 'region_cpu_ratio', 'region_idle',
|
|
'region_product_name', 'region_product_sku', 'region_start_time',
|
|
'sim_channel', 'sim_version', 'simulator_hostname',
|
|
'region_max_prims', # <http://wiki.secondlife.com/wiki/Release_Notes/Second_Life_RC_Magnum/16#16.11.02.321369>
|
|
'region_object_bonus')) # <http://wiki.secondlife.com/wiki/Release_Notes/Second_Life_RC_Magnum/16#16.12.03.322072>
|
|
|
|
xp_error_messages = {
|
|
-1:u'unknown error id',
|
|
0:u'no error', 1:u'exceeded throttle', 2:u'experiences are disabled',
|
|
3:u'invalid parameters', 4:u'operation not permitted',
|
|
5:u'script not associated with an experience', 6:u'not found',
|
|
7:u'invalid experience', 8:u'experience is disabled',
|
|
9:u'experience is suspended', 10:u'unknown error',
|
|
11:u'experience data quota exceeded',
|
|
12:u'key-value store is disabled',
|
|
13:u'key-value store communication failed', 14:u'key doesn\'t exist',
|
|
15:u'retry update', 16:u'experience content rating too high',
|
|
17:u'not allowed to run in current location',
|
|
18:u'experience permissions request timed out'
|
|
}
|
|
|
|
valid_inventory_kinds = frozenset((0, 1, 3, 5, 6, 7, 10, 13, 20, 21))
|
|
|
|
def llCloud(v):
|
|
v = v2f(v)
|
|
return 0.0
|
|
|
|
def llAvatarOnLinkSitTarget(link):
|
|
link = fi(link)
|
|
if link > 255 or link == -2147483648:
|
|
return Key(NULL_KEY)
|
|
raise ELSLCantCompute
|
|
|
|
# llClearPrimMedia always has side effects (emits errors for every face that
|
|
# is not supported)
|
|
def llClearLinkMedia(link, face):
|
|
if link > 255 or link == -2147483648:
|
|
return 0
|
|
raise ELSLCantCompute
|
|
|
|
def llDetectedGrab(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'grab' in evsym):
|
|
raise ELSLCantCompute
|
|
return ZERO_VECTOR
|
|
|
|
def llDetectedGroup(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
raise ELSLCantCompute
|
|
return 0
|
|
|
|
def llDetectedKey(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
raise ELSLCantCompute
|
|
return Key(NULL_KEY)
|
|
|
|
def llDetectedLinkNumber(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
raise ELSLCantCompute
|
|
return 0
|
|
|
|
def llDetectedName(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
raise ELSLCantCompute
|
|
return NULL_KEY
|
|
|
|
def llDetectedOwner(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
raise ELSLCantCompute
|
|
return Key(NULL_KEY)
|
|
|
|
def llDetectedPos(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
raise ELSLCantCompute
|
|
return ZERO_VECTOR
|
|
|
|
def llDetectedRot(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
raise ELSLCantCompute
|
|
return ZERO_ROTATION
|
|
|
|
def llDetectedTouchBinormal(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'touch' in evsym):
|
|
raise ELSLCantCompute
|
|
return ZERO_VECTOR
|
|
|
|
def llDetectedTouchFace(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'touch' in evsym):
|
|
raise ELSLCantCompute
|
|
return -1 if 'detect' in evsym and 0 <= idx <= 15 else 0
|
|
|
|
def llDetectedTouchNormal(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'touch' in evsym):
|
|
raise ELSLCantCompute
|
|
return ZERO_VECTOR
|
|
|
|
def llDetectedTouchPos(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'touch' in evsym):
|
|
raise ELSLCantCompute
|
|
return ZERO_VECTOR
|
|
|
|
def llDetectedTouchST(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
# In detection events that are not touch events, it returns
|
|
# TOUCH_INVALID_TEXCOORD if idx < num, else ZERO_VECTOR,
|
|
# but we only know that num >= 1.
|
|
if idx == 0 and evsym is not None and 'touch' not in evsym:
|
|
# index 0 always exists, so we know the result
|
|
return TOUCH_INVALID_TEXCOORD
|
|
raise ELSLCantCompute
|
|
return ZERO_VECTOR
|
|
|
|
def llDetectedTouchUV(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
# In detection events that are not touch events, it returns
|
|
# TOUCH_INVALID_TEXCOORD if idx < num, else ZERO_VECTOR,
|
|
# but we only know that num >= 1.
|
|
if idx == 0 and evsym is not None and 'touch' not in evsym:
|
|
# index 0 always exists, so we know the result
|
|
return TOUCH_INVALID_TEXCOORD
|
|
raise ELSLCantCompute
|
|
return ZERO_VECTOR
|
|
|
|
def llDetectedType(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
raise ELSLCantCompute
|
|
return 0
|
|
|
|
def llDetectedVel(idx, evsym=None):
|
|
idx = fi(idx)
|
|
if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym):
|
|
raise ELSLCantCompute
|
|
return ZERO_VECTOR
|
|
|
|
def llEdgeOfWorld(v1, v2):
|
|
v1 = v2f(v1)
|
|
v2 = v2f(v2)
|
|
if v2[0] == v2[1] == 0:
|
|
return 1
|
|
raise ELSLCantCompute
|
|
|
|
def llGetAgentInfo(id):
|
|
id = fk(id)
|
|
if not cond(id):
|
|
return 0
|
|
raise ELSLCantCompute
|
|
|
|
def llGetAgentLanguage(id):
|
|
id = fk(id)
|
|
if not cond(id):
|
|
return u''
|
|
raise ELSLCantCompute
|
|
|
|
def llGetAgentList(scope, options):
|
|
scope = fi(scope)
|
|
options = fl(options)
|
|
if scope not in (1, 2, 4):
|
|
return [u'INVALID_SCOPE']
|
|
raise ELSLCantCompute
|
|
|
|
def llGetAgentSize(id):
|
|
id = fk(id)
|
|
if not cond(id):
|
|
return ZERO_VECTOR
|
|
raise ELSLCantCompute
|
|
|
|
def llGetAlpha(face):
|
|
face = fi(face)
|
|
if face > 8:
|
|
return 1.0
|
|
# Negative face numbers return (float)llGetNumberOfSides(), which isn't
|
|
# computable.
|
|
raise ELSLCantCompute
|
|
|
|
def llGetAnimation(id):
|
|
id = fk(id)
|
|
if not cond(id):
|
|
return u''
|
|
raise ELSLCantCompute
|
|
|
|
def llGetAnimationList(id):
|
|
id = fk(id)
|
|
if not cond(id):
|
|
return []
|
|
raise ELSLCantCompute
|
|
|
|
def llGetAttachedList(id):
|
|
id = fk(id)
|
|
if not cond(id):
|
|
return [u'NOT FOUND']
|
|
raise ELSLCantCompute
|
|
|
|
def llGetBoundingBox(id):
|
|
id = fk(id)
|
|
if not cond(id):
|
|
return []
|
|
raise ELSLCantCompute
|
|
|
|
def llGetColor(face):
|
|
face = fi(face)
|
|
if face > 8:
|
|
return Vector((1.,1.,1.))
|
|
# Returns the average colour when negative (can't be computed)
|
|
raise ELSLCantCompute
|
|
|
|
def llGetDisplayName(id):
|
|
id = fk(id)
|
|
if not cond(id):
|
|
return u''
|
|
raise ELSLCantCompute
|
|
|
|
def llGetEnv(s):
|
|
s = fs(s)
|
|
if s not in GetEnvSettings:
|
|
return u""
|
|
raise ELSLCantCompute
|
|
|
|
def llGetExperienceErrorMessage(errno):
|
|
errno = fi(errno)
|
|
if errno < -1 or errno > 18:
|
|
errno = -1
|
|
return xp_error_messages[errno]
|
|
|
|
def llGetExperienceList(id):
|
|
id = fk(id)
|
|
# This function is not implemented and always returns empty list
|
|
return []
|
|
|
|
def llGetHTTPHeader(id, s):
|
|
id = fk(id)
|
|
s = fs(s)
|
|
if not cond(id):
|
|
return u''
|
|
raise ELSLCantCompute
|
|
|
|
def llGetInventoryKey(s):
|
|
s = fs(s)
|
|
if s == u'':
|
|
return Key(NULL_KEY)
|
|
raise ELSLCantCompute
|
|
|
|
def llGetInventoryName(kind, index):
|
|
kind = fi(kind)
|
|
index = fi(index)
|
|
if kind != -1 and kind not in valid_inventory_kinds or index < 0:
|
|
return u''
|
|
raise ELSLCantCompute
|
|
|
|
def llGetInventoryNumber(kind):
|
|
kind = fi(kind)
|
|
if kind != -1 and kind not in valid_inventory_kinds:
|
|
return 0
|
|
raise ELSLCantCompute
|
|
|
|
def llGetInventoryPermMask(item, category):
|
|
item = fs(item)
|
|
category = fi(category)
|
|
if category < 0 or category > 4 or item == u'':
|
|
return 0
|
|
raise ELSLCantCompute
|
|
|
|
|
|
def llGetOwnerKey(id):
|
|
id = fk(id)
|
|
if not cond(id):
|
|
return Key(NULL_KEY)
|
|
raise ELSLCantCompute
|
|
|
|
def llGetStatus(mask):
|
|
# leave out STATUS_DIE_AT_EDGE and STATUS_CAST_SHADOWS
|
|
if (mask & 0b10101111111) == 0:
|
|
return 0
|
|
raise ELSLCantCompute
|
|
|
|
# TODO: Add more predictable functions.
|