diff options
author | UbitUmarov | 2015-10-02 22:47:31 +0100 |
---|---|---|
committer | UbitUmarov | 2015-10-02 22:47:31 +0100 |
commit | 124602c6c25e0974dc5b4e260097c4ffa0d6bbf5 (patch) | |
tree | 0aa9a9523cde360dc272027a39b62062575d3313 /OpenSim/Region/ScriptEngine/Shared/Api | |
parent | put back ip check on llSetContentType (diff) | |
download | opensim-SC_OLD-124602c6c25e0974dc5b4e260097c4ffa0d6bbf5.zip opensim-SC_OLD-124602c6c25e0974dc5b4e260097c4ffa0d6bbf5.tar.gz opensim-SC_OLD-124602c6c25e0974dc5b4e260097c4ffa0d6bbf5.tar.bz2 opensim-SC_OLD-124602c6c25e0974dc5b4e260097c4ffa0d6bbf5.tar.xz |
reduce some diferences with master
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 516 |
1 files changed, 260 insertions, 256 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ba41499..33e34fb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -1928,7 +1928,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1928 | string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent"); | 1928 | string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent"); |
1929 | if (userAgent.IndexOf("SecondLife") < 0) | 1929 | if (userAgent.IndexOf("SecondLife") < 0) |
1930 | return; // Not the embedded browser. Is this check good enough? | 1930 | return; // Not the embedded browser. Is this check good enough? |
1931 | 1931 | ||
1932 | // Use the IP address of the client and check against the request | 1932 | // Use the IP address of the client and check against the request |
1933 | // seperate logins from the same IP will allow all of them to get non-text/plain as long | 1933 | // seperate logins from the same IP will allow all of them to get non-text/plain as long |
1934 | // as the owner is in the region. Same as SL! | 1934 | // as the owner is in the region. Same as SL! |
@@ -2174,9 +2174,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2174 | foreach (SceneObjectPart part in parts) | 2174 | foreach (SceneObjectPart part in parts) |
2175 | SetAlpha(part, alpha, face); | 2175 | SetAlpha(part, alpha, face); |
2176 | } | 2176 | } |
2177 | finally | 2177 | finally { } |
2178 | { | ||
2179 | } | ||
2180 | } | 2178 | } |
2181 | } | 2179 | } |
2182 | 2180 | ||
@@ -2366,10 +2364,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2366 | foreach (SceneObjectPart part in parts) | 2364 | foreach (SceneObjectPart part in parts) |
2367 | SetTexture(part, texture, face); | 2365 | SetTexture(part, texture, face); |
2368 | } | 2366 | } |
2369 | finally | 2367 | finally { } |
2370 | { | 2368 | } |
2371 | } | ||
2372 | } | ||
2373 | ScriptSleep(m_sleepMsOnSetLinkTexture); | 2369 | ScriptSleep(m_sleepMsOnSetLinkTexture); |
2374 | } | 2370 | } |
2375 | 2371 | ||
@@ -2736,13 +2732,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2736 | public void llSetRot(LSL_Rotation rot) | 2732 | public void llSetRot(LSL_Rotation rot) |
2737 | { | 2733 | { |
2738 | m_host.AddScriptLPS(1); | 2734 | m_host.AddScriptLPS(1); |
2739 | 2735 | ||
2740 | |||
2741 | // Teravus: if (m_host.ParentID == 0) is bug code because the ParentID for the Avatar will cause this to be nonzero for root prim attachments | ||
2742 | // which is then treated like a child prim rotation and it's offset gets cumulatively multiplied against. | ||
2743 | // to fix the scripted rotations we also have to check to see if the root part localid is the same as the host's localid. | ||
2744 | // RootPart != null should shortcircuit | ||
2745 | |||
2746 | // try to let this work as in SL... | 2736 | // try to let this work as in SL... |
2747 | if (m_host.ParentID == 0 || (m_host.ParentGroup != null && m_host == m_host.ParentGroup.RootPart)) | 2737 | if (m_host.ParentID == 0 || (m_host.ParentGroup != null && m_host == m_host.ParentGroup.RootPart)) |
2748 | { | 2738 | { |
@@ -2781,7 +2771,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2781 | 2771 | ||
2782 | // keep using physactor ideia of isphysical | 2772 | // keep using physactor ideia of isphysical |
2783 | // it should be SOP ideia of that | 2773 | // it should be SOP ideia of that |
2784 | // not much of a issue with ubitODE | 2774 | // not much of a issue with ubOde |
2785 | if (pa != null && pa.IsPhysical) | 2775 | if (pa != null && pa.IsPhysical) |
2786 | isphys = true; | 2776 | isphys = true; |
2787 | else | 2777 | else |
@@ -2923,6 +2913,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2923 | return force; | 2913 | return force; |
2924 | } | 2914 | } |
2925 | 2915 | ||
2916 | public void llSetVelocity(LSL_Vector vel, int local) | ||
2917 | { | ||
2918 | m_host.AddScriptLPS(1); | ||
2919 | m_host.SetVelocity(new Vector3((float)vel.x, (float)vel.y, (float)vel.z), local != 0); | ||
2920 | } | ||
2921 | |||
2922 | public void llSetAngularVelocity(LSL_Vector avel, int local) | ||
2923 | { | ||
2924 | m_host.AddScriptLPS(1); | ||
2925 | m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0); | ||
2926 | } | ||
2926 | public LSL_Integer llTarget(LSL_Vector position, double range) | 2927 | public LSL_Integer llTarget(LSL_Vector position, double range) |
2927 | { | 2928 | { |
2928 | m_host.AddScriptLPS(1); | 2929 | m_host.AddScriptLPS(1); |
@@ -3000,11 +3001,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3000 | llSetTorque(torque, local); | 3001 | llSetTorque(torque, local); |
3001 | } | 3002 | } |
3002 | 3003 | ||
3003 | public void llSetVelocity(LSL_Vector vel, int local) | ||
3004 | { | ||
3005 | m_host.AddScriptLPS(1); | ||
3006 | m_host.SetVelocity(new Vector3((float)vel.x, (float)vel.y, (float)vel.z), local != 0); | ||
3007 | } | ||
3008 | 3004 | ||
3009 | public LSL_Vector llGetVel() | 3005 | public LSL_Vector llGetVel() |
3010 | { | 3006 | { |
@@ -3033,12 +3029,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3033 | return new LSL_Vector(m_host.Acceleration); | 3029 | return new LSL_Vector(m_host.Acceleration); |
3034 | } | 3030 | } |
3035 | 3031 | ||
3036 | public void llSetAngularVelocity(LSL_Vector avel, int local) | ||
3037 | { | ||
3038 | m_host.AddScriptLPS(1); | ||
3039 | m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0); | ||
3040 | } | ||
3041 | |||
3042 | public LSL_Vector llGetOmega() | 3032 | public LSL_Vector llGetOmega() |
3043 | { | 3033 | { |
3044 | m_host.AddScriptLPS(1); | 3034 | m_host.AddScriptLPS(1); |
@@ -3700,6 +3690,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3700 | { | 3690 | { |
3701 | // Unregister controls from Presence | 3691 | // Unregister controls from Presence |
3702 | presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID); | 3692 | presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID); |
3693 | // Remove Take Control permission. | ||
3694 | m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; | ||
3703 | } | 3695 | } |
3704 | } | 3696 | } |
3705 | } | 3697 | } |
@@ -4289,9 +4281,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4289 | foreach (SceneObjectPart part in parts) | 4281 | foreach (SceneObjectPart part in parts) |
4290 | part.SetFaceColorAlpha(face, color, null); | 4282 | part.SetFaceColorAlpha(face, color, null); |
4291 | } | 4283 | } |
4292 | finally | 4284 | finally { } |
4293 | { | ||
4294 | } | ||
4295 | } | 4285 | } |
4296 | } | 4286 | } |
4297 | 4287 | ||
@@ -4428,10 +4418,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4428 | parentPrim.DelinkFromGroup(part.LocalId, true); | 4418 | parentPrim.DelinkFromGroup(part.LocalId, true); |
4429 | } | 4419 | } |
4430 | } | 4420 | } |
4431 | finally | 4421 | finally { } |
4432 | { | 4422 | } |
4433 | } | ||
4434 | } | ||
4435 | 4423 | ||
4436 | parentPrim.HasGroupChanged = true; | 4424 | parentPrim.HasGroupChanged = true; |
4437 | parentPrim.ScheduleGroupForFullUpdate(); | 4425 | parentPrim.ScheduleGroupForFullUpdate(); |
@@ -4450,10 +4438,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4450 | newRoot.ParentGroup.LinkToGroup(part.ParentGroup); | 4438 | newRoot.ParentGroup.LinkToGroup(part.ParentGroup); |
4451 | } | 4439 | } |
4452 | } | 4440 | } |
4453 | finally | 4441 | finally { } |
4454 | { | ||
4455 | } | ||
4456 | |||
4457 | 4442 | ||
4458 | newRoot.ParentGroup.HasGroupChanged = true; | 4443 | newRoot.ParentGroup.HasGroupChanged = true; |
4459 | newRoot.ParentGroup.ScheduleGroupForFullUpdate(); | 4444 | newRoot.ParentGroup.ScheduleGroupForFullUpdate(); |
@@ -4847,24 +4832,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4847 | 4832 | ||
4848 | switch (data) | 4833 | switch (data) |
4849 | { | 4834 | { |
4850 | case 1: // DATA_ONLINE (0|1) | 4835 | case ScriptBaseClass.DATA_ONLINE: // DATA_ONLINE (0|1) |
4851 | if (pinfo != null && pinfo.RegionID != UUID.Zero) | 4836 | if (pinfo != null && pinfo.RegionID != UUID.Zero) |
4852 | reply = "1"; | 4837 | reply = "1"; |
4853 | else | 4838 | else |
4854 | reply = "0"; | 4839 | reply = "0"; |
4855 | break; | 4840 | break; |
4856 | case 2: // DATA_NAME (First Last) | 4841 | case ScriptBaseClass.DATA_NAME: // DATA_NAME (First Last) |
4857 | reply = account.FirstName + " " + account.LastName; | 4842 | reply = account.FirstName + " " + account.LastName; |
4858 | break; | 4843 | break; |
4859 | case 3: // DATA_BORN (YYYY-MM-DD) | 4844 | case ScriptBaseClass.DATA_BORN: // DATA_BORN (YYYY-MM-DD) |
4860 | DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); | 4845 | DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); |
4861 | born = born.AddSeconds(account.Created); | 4846 | born = born.AddSeconds(account.Created); |
4862 | reply = born.ToString("yyyy-MM-dd"); | 4847 | reply = born.ToString("yyyy-MM-dd"); |
4863 | break; | 4848 | break; |
4864 | case 4: // DATA_RATING (0,0,0,0,0,0) | 4849 | case ScriptBaseClass.DATA_RATING: // DATA_RATING (0,0,0,0,0,0) |
4865 | reply = "0,0,0,0,0,0"; | 4850 | reply = "0,0,0,0,0,0"; |
4866 | break; | 4851 | break; |
4867 | case 8: // DATA_PAYINFO (0|1|2|3) | 4852 | case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant. |
4853 | reply = account.UserLevel.ToString(); | ||
4854 | break; | ||
4855 | case ScriptBaseClass.DATA_PAYINFO: // DATA_PAYINFO (0|1|2|3) | ||
4868 | reply = "0"; | 4856 | reply = "0"; |
4869 | break; | 4857 | break; |
4870 | default: | 4858 | default: |
@@ -5025,22 +5013,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5025 | 5013 | ||
5026 | ScenePresence presence = World.GetScenePresence(agentId); | 5014 | ScenePresence presence = World.GetScenePresence(agentId); |
5027 | 5015 | ||
5016 | if (presence == null || presence.PresenceType == PresenceType.Npc) | ||
5017 | return; | ||
5018 | |||
5028 | // Can't TP sitting avatars | 5019 | // Can't TP sitting avatars |
5029 | if (presence.ParentID != 0) // Sitting | 5020 | if (presence.ParentID != 0) // Sitting |
5030 | return; | 5021 | return; |
5031 | 5022 | ||
5032 | if (presence != null && presence.PresenceType != PresenceType.Npc) | 5023 | if (m_item.PermsGranter == agentId) |
5033 | { | 5024 | { |
5034 | if (m_item.PermsGranter == agentId) | 5025 | // If attached using llAttachToAvatarTemp, cowardly refuse |
5035 | { | 5026 | if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.ParentGroup.FromItemID == UUID.Zero) |
5036 | // If attached using llAttachToAvatarTemp, cowardly refuse | 5027 | return; |
5037 | if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.ParentGroup.FromItemID == UUID.Zero) | ||
5038 | return; | ||
5039 | 5028 | ||
5040 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0) | 5029 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0) |
5041 | { | 5030 | { |
5042 | World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); | 5031 | World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); |
5043 | } | ||
5044 | } | 5032 | } |
5045 | } | 5033 | } |
5046 | } | 5034 | } |
@@ -8583,6 +8571,142 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8583 | } | 8571 | } |
8584 | } | 8572 | } |
8585 | 8573 | ||
8574 | public void llSetKeyframedMotion(LSL_List frames, LSL_List options) | ||
8575 | { | ||
8576 | SceneObjectGroup group = m_host.ParentGroup; | ||
8577 | |||
8578 | if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical) | ||
8579 | return; | ||
8580 | if (group.IsAttachment) | ||
8581 | return; | ||
8582 | |||
8583 | if (frames.Data.Length > 0) // We are getting a new motion | ||
8584 | { | ||
8585 | if (group.RootPart.KeyframeMotion != null) | ||
8586 | group.RootPart.KeyframeMotion.Delete(); | ||
8587 | group.RootPart.KeyframeMotion = null; | ||
8588 | |||
8589 | int idx = 0; | ||
8590 | |||
8591 | KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward; | ||
8592 | KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation; | ||
8593 | |||
8594 | while (idx < options.Data.Length) | ||
8595 | { | ||
8596 | int option = (int)options.GetLSLIntegerItem(idx++); | ||
8597 | int remain = options.Data.Length - idx; | ||
8598 | |||
8599 | switch (option) | ||
8600 | { | ||
8601 | case ScriptBaseClass.KFM_MODE: | ||
8602 | if (remain < 1) | ||
8603 | break; | ||
8604 | int modeval = (int)options.GetLSLIntegerItem(idx++); | ||
8605 | switch(modeval) | ||
8606 | { | ||
8607 | case ScriptBaseClass.KFM_FORWARD: | ||
8608 | mode = KeyframeMotion.PlayMode.Forward; | ||
8609 | break; | ||
8610 | case ScriptBaseClass.KFM_REVERSE: | ||
8611 | mode = KeyframeMotion.PlayMode.Reverse; | ||
8612 | break; | ||
8613 | case ScriptBaseClass.KFM_LOOP: | ||
8614 | mode = KeyframeMotion.PlayMode.Loop; | ||
8615 | break; | ||
8616 | case ScriptBaseClass.KFM_PING_PONG: | ||
8617 | mode = KeyframeMotion.PlayMode.PingPong; | ||
8618 | break; | ||
8619 | } | ||
8620 | break; | ||
8621 | case ScriptBaseClass.KFM_DATA: | ||
8622 | if (remain < 1) | ||
8623 | break; | ||
8624 | int dataval = (int)options.GetLSLIntegerItem(idx++); | ||
8625 | data = (KeyframeMotion.DataFormat)dataval; | ||
8626 | break; | ||
8627 | } | ||
8628 | } | ||
8629 | |||
8630 | group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data); | ||
8631 | |||
8632 | idx = 0; | ||
8633 | |||
8634 | int elemLength = 2; | ||
8635 | if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation)) | ||
8636 | elemLength = 3; | ||
8637 | |||
8638 | List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>(); | ||
8639 | while (idx < frames.Data.Length) | ||
8640 | { | ||
8641 | int remain = frames.Data.Length - idx; | ||
8642 | |||
8643 | if (remain < elemLength) | ||
8644 | break; | ||
8645 | |||
8646 | KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe(); | ||
8647 | frame.Position = null; | ||
8648 | frame.Rotation = null; | ||
8649 | |||
8650 | if ((data & KeyframeMotion.DataFormat.Translation) != 0) | ||
8651 | { | ||
8652 | LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++); | ||
8653 | frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z); | ||
8654 | } | ||
8655 | if ((data & KeyframeMotion.DataFormat.Rotation) != 0) | ||
8656 | { | ||
8657 | LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++); | ||
8658 | Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s); | ||
8659 | q.Normalize(); | ||
8660 | frame.Rotation = q; | ||
8661 | } | ||
8662 | |||
8663 | float tempf = (float)frames.GetLSLFloatItem(idx++); | ||
8664 | frame.TimeMS = (int)(tempf * 1000.0f); | ||
8665 | |||
8666 | keyframes.Add(frame); | ||
8667 | } | ||
8668 | |||
8669 | group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray()); | ||
8670 | group.RootPart.KeyframeMotion.Start(); | ||
8671 | } | ||
8672 | else | ||
8673 | { | ||
8674 | if (group.RootPart.KeyframeMotion == null) | ||
8675 | return; | ||
8676 | |||
8677 | if (options.Data.Length == 0) | ||
8678 | { | ||
8679 | group.RootPart.KeyframeMotion.Stop(); | ||
8680 | return; | ||
8681 | } | ||
8682 | |||
8683 | int idx = 0; | ||
8684 | |||
8685 | while (idx < options.Data.Length) | ||
8686 | { | ||
8687 | int option = (int)options.GetLSLIntegerItem(idx++); | ||
8688 | |||
8689 | switch (option) | ||
8690 | { | ||
8691 | case ScriptBaseClass.KFM_COMMAND: | ||
8692 | int cmd = (int)options.GetLSLIntegerItem(idx++); | ||
8693 | switch (cmd) | ||
8694 | { | ||
8695 | case ScriptBaseClass.KFM_CMD_PLAY: | ||
8696 | group.RootPart.KeyframeMotion.Start(); | ||
8697 | break; | ||
8698 | case ScriptBaseClass.KFM_CMD_STOP: | ||
8699 | group.RootPart.KeyframeMotion.Stop(); | ||
8700 | break; | ||
8701 | case ScriptBaseClass.KFM_CMD_PAUSE: | ||
8702 | group.RootPart.KeyframeMotion.Pause(); | ||
8703 | break; | ||
8704 | } | ||
8705 | break; | ||
8706 | } | ||
8707 | } | ||
8708 | } | ||
8709 | } | ||
8586 | 8710 | ||
8587 | public LSL_List llGetPhysicsMaterial() | 8711 | public LSL_List llGetPhysicsMaterial() |
8588 | { | 8712 | { |
@@ -8682,7 +8806,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8682 | if (remain < 1) | 8806 | if (remain < 1) |
8683 | return new LSL_List(); | 8807 | return new LSL_List(); |
8684 | 8808 | ||
8685 | v=rules.GetVector3Item(idx++); | 8809 | try |
8810 | { | ||
8811 | v = rules.GetVector3Item(idx++); | ||
8812 | } | ||
8813 | catch(InvalidCastException) | ||
8814 | { | ||
8815 | if(code == ScriptBaseClass.PRIM_POSITION) | ||
8816 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8817 | else | ||
8818 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8819 | return new LSL_List(); | ||
8820 | } | ||
8686 | if (part.IsRoot && !part.ParentGroup.IsAttachment) | 8821 | if (part.IsRoot && !part.ParentGroup.IsAttachment) |
8687 | currentPosition = GetSetPosTarget(part, v, currentPosition, true); | 8822 | currentPosition = GetSetPosTarget(part, v, currentPosition, true); |
8688 | else | 8823 | else |
@@ -10444,6 +10579,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10444 | return result; | 10579 | return result; |
10445 | } | 10580 | } |
10446 | 10581 | ||
10582 | /// <summary> | ||
10583 | /// Helper to calculate bounding box of an avatar. | ||
10584 | /// </summary> | ||
10585 | private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper) | ||
10586 | { | ||
10587 | // Adjust from OS model | ||
10588 | // avatar height = visual height - 0.2, bounding box height = visual height | ||
10589 | // to SL model | ||
10590 | // avatar height = visual height, bounding box height = visual height + 0.2 | ||
10591 | float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection; | ||
10592 | |||
10593 | // According to avatar bounding box in SL 2015-04-18: | ||
10594 | // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h> | ||
10595 | // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5> | ||
10596 | // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h> | ||
10597 | |||
10598 | // When avatar is sitting | ||
10599 | if (sp.ParentPart != null) | ||
10600 | { | ||
10601 | lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height); | ||
10602 | upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height); | ||
10603 | } | ||
10604 | // When avatar is groundsitting | ||
10605 | else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) | ||
10606 | { | ||
10607 | lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height); | ||
10608 | upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height); | ||
10609 | } | ||
10610 | // When avatar is standing or flying | ||
10611 | else | ||
10612 | { | ||
10613 | lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height); | ||
10614 | upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height); | ||
10615 | } | ||
10616 | } | ||
10617 | |||
10618 | |||
10447 | public LSL_Vector llGetGeometricCenter() | 10619 | public LSL_Vector llGetGeometricCenter() |
10448 | { | 10620 | { |
10449 | return new LSL_Vector(m_host.GetGeometricCenter()); | 10621 | return new LSL_Vector(m_host.GetGeometricCenter()); |
@@ -10560,6 +10732,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10560 | res.Add(GetPartRot(part)); | 10732 | res.Add(GetPartRot(part)); |
10561 | break; | 10733 | break; |
10562 | 10734 | ||
10735 | case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: | ||
10736 | res.Add(new LSL_Integer((int)part.PhysicsShapeType)); | ||
10737 | break; | ||
10738 | |||
10563 | case (int)ScriptBaseClass.PRIM_TYPE: | 10739 | case (int)ScriptBaseClass.PRIM_TYPE: |
10564 | // implementing box | 10740 | // implementing box |
10565 | PrimitiveBaseShape Shape = part.Shape; | 10741 | PrimitiveBaseShape Shape = part.Shape; |
@@ -12116,17 +12292,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12116 | int width = 0; | 12292 | int width = 0; |
12117 | int height = 0; | 12293 | int height = 0; |
12118 | 12294 | ||
12119 | uint commandToSend = 0; | 12295 | ParcelMediaCommandEnum? commandToSend = null; |
12120 | float time = 0.0f; // default is from start | 12296 | float time = 0.0f; // default is from start |
12121 | 12297 | ||
12122 | ScenePresence presence = null; | 12298 | ScenePresence presence = null; |
12123 | 12299 | ||
12124 | for (int i = 0; i < commandList.Data.Length; i++) | 12300 | for (int i = 0; i < commandList.Data.Length; i++) |
12125 | { | 12301 | { |
12126 | uint command = (uint)(commandList.GetLSLIntegerItem(i)); | 12302 | ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; |
12127 | switch (command) | 12303 | switch (command) |
12128 | { | 12304 | { |
12129 | case (uint)ParcelMediaCommandEnum.Agent: | 12305 | case ParcelMediaCommandEnum.Agent: |
12130 | // we send only to one agent | 12306 | // we send only to one agent |
12131 | if ((i + 1) < commandList.Length) | 12307 | if ((i + 1) < commandList.Length) |
12132 | { | 12308 | { |
@@ -12143,25 +12319,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12143 | } | 12319 | } |
12144 | break; | 12320 | break; |
12145 | 12321 | ||
12146 | case (uint)ParcelMediaCommandEnum.Loop: | 12322 | case ParcelMediaCommandEnum.Loop: |
12147 | loop = 1; | 12323 | loop = 1; |
12148 | commandToSend = command; | 12324 | commandToSend = command; |
12149 | update = true; //need to send the media update packet to set looping | 12325 | update = true; //need to send the media update packet to set looping |
12150 | break; | 12326 | break; |
12151 | 12327 | ||
12152 | case (uint)ParcelMediaCommandEnum.Play: | 12328 | case ParcelMediaCommandEnum.Play: |
12153 | loop = 0; | 12329 | loop = 0; |
12154 | commandToSend = command; | 12330 | commandToSend = command; |
12155 | update = true; //need to send the media update packet to make sure it doesn't loop | 12331 | update = true; //need to send the media update packet to make sure it doesn't loop |
12156 | break; | 12332 | break; |
12157 | 12333 | ||
12158 | case (uint)ParcelMediaCommandEnum.Pause: | 12334 | case ParcelMediaCommandEnum.Pause: |
12159 | case (uint)ParcelMediaCommandEnum.Stop: | 12335 | case ParcelMediaCommandEnum.Stop: |
12160 | case (uint)ParcelMediaCommandEnum.Unload: | 12336 | case ParcelMediaCommandEnum.Unload: |
12161 | commandToSend = command; | 12337 | commandToSend = command; |
12162 | break; | 12338 | break; |
12163 | 12339 | ||
12164 | case (uint)ParcelMediaCommandEnum.Url: | 12340 | case ParcelMediaCommandEnum.Url: |
12165 | if ((i + 1) < commandList.Length) | 12341 | if ((i + 1) < commandList.Length) |
12166 | { | 12342 | { |
12167 | if (commandList.Data[i + 1] is LSL_String) | 12343 | if (commandList.Data[i + 1] is LSL_String) |
@@ -12174,7 +12350,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12174 | } | 12350 | } |
12175 | break; | 12351 | break; |
12176 | 12352 | ||
12177 | case (uint)ParcelMediaCommandEnum.Texture: | 12353 | case ParcelMediaCommandEnum.Texture: |
12178 | if ((i + 1) < commandList.Length) | 12354 | if ((i + 1) < commandList.Length) |
12179 | { | 12355 | { |
12180 | if (commandList.Data[i + 1] is LSL_String) | 12356 | if (commandList.Data[i + 1] is LSL_String) |
@@ -12187,7 +12363,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12187 | } | 12363 | } |
12188 | break; | 12364 | break; |
12189 | 12365 | ||
12190 | case (uint)ParcelMediaCommandEnum.Time: | 12366 | case ParcelMediaCommandEnum.Time: |
12191 | if ((i + 1) < commandList.Length) | 12367 | if ((i + 1) < commandList.Length) |
12192 | { | 12368 | { |
12193 | if (commandList.Data[i + 1] is LSL_Float) | 12369 | if (commandList.Data[i + 1] is LSL_Float) |
@@ -12199,7 +12375,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12199 | } | 12375 | } |
12200 | break; | 12376 | break; |
12201 | 12377 | ||
12202 | case (uint)ParcelMediaCommandEnum.AutoAlign: | 12378 | case ParcelMediaCommandEnum.AutoAlign: |
12203 | if ((i + 1) < commandList.Length) | 12379 | if ((i + 1) < commandList.Length) |
12204 | { | 12380 | { |
12205 | if (commandList.Data[i + 1] is LSL_Integer) | 12381 | if (commandList.Data[i + 1] is LSL_Integer) |
@@ -12213,7 +12389,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12213 | } | 12389 | } |
12214 | break; | 12390 | break; |
12215 | 12391 | ||
12216 | case (uint)ParcelMediaCommandEnum.Type: | 12392 | case ParcelMediaCommandEnum.Type: |
12217 | if ((i + 1) < commandList.Length) | 12393 | if ((i + 1) < commandList.Length) |
12218 | { | 12394 | { |
12219 | if (commandList.Data[i + 1] is LSL_String) | 12395 | if (commandList.Data[i + 1] is LSL_String) |
@@ -12226,7 +12402,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12226 | } | 12402 | } |
12227 | break; | 12403 | break; |
12228 | 12404 | ||
12229 | case (uint)ParcelMediaCommandEnum.Desc: | 12405 | case ParcelMediaCommandEnum.Desc: |
12230 | if ((i + 1) < commandList.Length) | 12406 | if ((i + 1) < commandList.Length) |
12231 | { | 12407 | { |
12232 | if (commandList.Data[i + 1] is LSL_String) | 12408 | if (commandList.Data[i + 1] is LSL_String) |
@@ -12239,7 +12415,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12239 | } | 12415 | } |
12240 | break; | 12416 | break; |
12241 | 12417 | ||
12242 | case (uint)ParcelMediaCommandEnum.Size: | 12418 | case ParcelMediaCommandEnum.Size: |
12243 | if ((i + 2) < commandList.Length) | 12419 | if ((i + 2) < commandList.Length) |
12244 | { | 12420 | { |
12245 | if (commandList.Data[i + 1] is LSL_Integer) | 12421 | if (commandList.Data[i + 1] is LSL_Integer) |
@@ -12309,7 +12485,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12309 | } | 12485 | } |
12310 | } | 12486 | } |
12311 | 12487 | ||
12312 | if (commandToSend != 0) | 12488 | if (commandToSend != null) |
12313 | { | 12489 | { |
12314 | // the commandList contained a start/stop/... command, too | 12490 | // the commandList contained a start/stop/... command, too |
12315 | if (presence == null) | 12491 | if (presence == null) |
@@ -12320,16 +12496,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12320 | if (sp.currentParcelUUID == landData.GlobalID) | 12496 | if (sp.currentParcelUUID == landData.GlobalID) |
12321 | { | 12497 | { |
12322 | sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? | 12498 | sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? |
12323 | (ParcelMediaCommandEnum)commandToSend, | 12499 | (ParcelMediaCommandEnum)commandToSend, time); |
12324 | time); | ||
12325 | } | 12500 | } |
12326 | }); | 12501 | }); |
12327 | } | 12502 | } |
12328 | else if (!presence.IsChildAgent) | 12503 | else if (!presence.IsChildAgent) |
12329 | { | 12504 | { |
12330 | presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? | 12505 | presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? |
12331 | (ParcelMediaCommandEnum)commandToSend, | 12506 | (ParcelMediaCommandEnum)commandToSend, time); |
12332 | time); | ||
12333 | } | 12507 | } |
12334 | } | 12508 | } |
12335 | ScriptSleep(m_sleepMsOnParcelMediaCommandList); | 12509 | ScriptSleep(m_sleepMsOnParcelMediaCommandList); |
@@ -13815,6 +13989,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
13815 | return result; | 13989 | return result; |
13816 | } | 13990 | } |
13817 | 13991 | ||
13992 | public void print(string str) | ||
13993 | { | ||
13994 | // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print | ||
13995 | IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); | ||
13996 | if (ossl != null) | ||
13997 | { | ||
13998 | ossl.CheckThreatLevel(ThreatLevel.High, "print"); | ||
13999 | m_log.Info("LSL print():" + str); | ||
14000 | } | ||
14001 | } | ||
14002 | |||
13818 | public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) | 14003 | public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) |
13819 | { | 14004 | { |
13820 | List<SceneObjectPart> parts = GetLinkParts(link); | 14005 | List<SceneObjectPart> parts = GetLinkParts(link); |
@@ -14384,47 +14569,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
14384 | 14569 | ||
14385 | return list; | 14570 | return list; |
14386 | } | 14571 | } |
14387 | |||
14388 | |||
14389 | // this is wrong, except on a few trivial cases | ||
14390 | // keeping it for now just for raycast v3 | ||
14391 | 14572 | ||
14392 | /// <summary> | ||
14393 | /// Helper to calculate bounding box of an avatar. | ||
14394 | /// </summary> | ||
14395 | private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper) | ||
14396 | { | ||
14397 | // Adjust from OS model | ||
14398 | // avatar height = visual height - 0.2, bounding box height = visual height | ||
14399 | // to SL model | ||
14400 | // avatar height = visual height, bounding box height = visual height + 0.2 | ||
14401 | float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection; | ||
14402 | |||
14403 | // According to avatar bounding box in SL 2015-04-18: | ||
14404 | // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h> | ||
14405 | // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5> | ||
14406 | // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h> | ||
14407 | |||
14408 | // When avatar is sitting | ||
14409 | if (sp.ParentPart != null) | ||
14410 | { | ||
14411 | lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height); | ||
14412 | upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height); | ||
14413 | } | ||
14414 | // When avatar is groundsitting | ||
14415 | else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) | ||
14416 | { | ||
14417 | lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height); | ||
14418 | upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height); | ||
14419 | } | ||
14420 | // When avatar is standing or flying | ||
14421 | else | ||
14422 | { | ||
14423 | lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height); | ||
14424 | upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height); | ||
14425 | } | ||
14426 | } | ||
14427 | |||
14428 | 14573 | ||
14429 | /// <summary> | 14574 | /// <summary> |
14430 | /// Implementation of llCastRay similar to SL 2015-04-21. | 14575 | /// Implementation of llCastRay similar to SL 2015-04-21. |
@@ -15547,145 +15692,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
15547 | 15692 | ||
15548 | #endregion | 15693 | #endregion |
15549 | 15694 | ||
15550 | public void llSetKeyframedMotion(LSL_List frames, LSL_List options) | ||
15551 | { | ||
15552 | SceneObjectGroup group = m_host.ParentGroup; | ||
15553 | |||
15554 | if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical) | ||
15555 | return; | ||
15556 | if (group.IsAttachment) | ||
15557 | return; | ||
15558 | |||
15559 | if (frames.Data.Length > 0) // We are getting a new motion | ||
15560 | { | ||
15561 | if (group.RootPart.KeyframeMotion != null) | ||
15562 | group.RootPart.KeyframeMotion.Delete(); | ||
15563 | group.RootPart.KeyframeMotion = null; | ||
15564 | |||
15565 | int idx = 0; | ||
15566 | |||
15567 | KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward; | ||
15568 | KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation; | ||
15569 | |||
15570 | while (idx < options.Data.Length) | ||
15571 | { | ||
15572 | int option = (int)options.GetLSLIntegerItem(idx++); | ||
15573 | int remain = options.Data.Length - idx; | ||
15574 | |||
15575 | switch (option) | ||
15576 | { | ||
15577 | case ScriptBaseClass.KFM_MODE: | ||
15578 | if (remain < 1) | ||
15579 | break; | ||
15580 | int modeval = (int)options.GetLSLIntegerItem(idx++); | ||
15581 | switch(modeval) | ||
15582 | { | ||
15583 | case ScriptBaseClass.KFM_FORWARD: | ||
15584 | mode = KeyframeMotion.PlayMode.Forward; | ||
15585 | break; | ||
15586 | case ScriptBaseClass.KFM_REVERSE: | ||
15587 | mode = KeyframeMotion.PlayMode.Reverse; | ||
15588 | break; | ||
15589 | case ScriptBaseClass.KFM_LOOP: | ||
15590 | mode = KeyframeMotion.PlayMode.Loop; | ||
15591 | break; | ||
15592 | case ScriptBaseClass.KFM_PING_PONG: | ||
15593 | mode = KeyframeMotion.PlayMode.PingPong; | ||
15594 | break; | ||
15595 | } | ||
15596 | break; | ||
15597 | case ScriptBaseClass.KFM_DATA: | ||
15598 | if (remain < 1) | ||
15599 | break; | ||
15600 | int dataval = (int)options.GetLSLIntegerItem(idx++); | ||
15601 | data = (KeyframeMotion.DataFormat)dataval; | ||
15602 | break; | ||
15603 | } | ||
15604 | } | ||
15605 | |||
15606 | group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data); | ||
15607 | |||
15608 | idx = 0; | ||
15609 | |||
15610 | int elemLength = 2; | ||
15611 | if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation)) | ||
15612 | elemLength = 3; | ||
15613 | |||
15614 | List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>(); | ||
15615 | while (idx < frames.Data.Length) | ||
15616 | { | ||
15617 | int remain = frames.Data.Length - idx; | ||
15618 | |||
15619 | if (remain < elemLength) | ||
15620 | break; | ||
15621 | |||
15622 | KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe(); | ||
15623 | frame.Position = null; | ||
15624 | frame.Rotation = null; | ||
15625 | |||
15626 | if ((data & KeyframeMotion.DataFormat.Translation) != 0) | ||
15627 | { | ||
15628 | LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++); | ||
15629 | frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z); | ||
15630 | } | ||
15631 | if ((data & KeyframeMotion.DataFormat.Rotation) != 0) | ||
15632 | { | ||
15633 | LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++); | ||
15634 | Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s); | ||
15635 | q.Normalize(); | ||
15636 | frame.Rotation = q; | ||
15637 | } | ||
15638 | |||
15639 | float tempf = (float)frames.GetLSLFloatItem(idx++); | ||
15640 | frame.TimeMS = (int)(tempf * 1000.0f); | ||
15641 | |||
15642 | keyframes.Add(frame); | ||
15643 | } | ||
15644 | |||
15645 | group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray()); | ||
15646 | group.RootPart.KeyframeMotion.Start(); | ||
15647 | } | ||
15648 | else | ||
15649 | { | ||
15650 | if (group.RootPart.KeyframeMotion == null) | ||
15651 | return; | ||
15652 | |||
15653 | if (options.Data.Length == 0) | ||
15654 | { | ||
15655 | group.RootPart.KeyframeMotion.Stop(); | ||
15656 | return; | ||
15657 | } | ||
15658 | |||
15659 | int code = (int)options.GetLSLIntegerItem(0); | ||
15660 | |||
15661 | int idx = 0; | ||
15662 | |||
15663 | while (idx < options.Data.Length) | ||
15664 | { | ||
15665 | int option = (int)options.GetLSLIntegerItem(idx++); | ||
15666 | int remain = options.Data.Length - idx; | ||
15667 | |||
15668 | switch (option) | ||
15669 | { | ||
15670 | case ScriptBaseClass.KFM_COMMAND: | ||
15671 | int cmd = (int)options.GetLSLIntegerItem(idx++); | ||
15672 | switch (cmd) | ||
15673 | { | ||
15674 | case ScriptBaseClass.KFM_CMD_PLAY: | ||
15675 | group.RootPart.KeyframeMotion.Start(); | ||
15676 | break; | ||
15677 | case ScriptBaseClass.KFM_CMD_STOP: | ||
15678 | group.RootPart.KeyframeMotion.Stop(); | ||
15679 | break; | ||
15680 | case ScriptBaseClass.KFM_CMD_PAUSE: | ||
15681 | group.RootPart.KeyframeMotion.Pause(); | ||
15682 | break; | ||
15683 | } | ||
15684 | break; | ||
15685 | } | ||
15686 | } | ||
15687 | } | ||
15688 | } | ||
15689 | 15695 | ||
15690 | protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed) | 15696 | protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed) |
15691 | { | 15697 | { |
@@ -16104,8 +16110,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
16104 | return new LSL_List(); | 16110 | return new LSL_List(); |
16105 | } | 16111 | } |
16106 | 16112 | ||
16107 | |||
16108 | |||
16109 | public void llSetAnimationOverride(LSL_String animState, LSL_String anim) | 16113 | public void llSetAnimationOverride(LSL_String animState, LSL_String anim) |
16110 | { | 16114 | { |
16111 | string state = String.Empty; | 16115 | string state = String.Empty; |