From 9468917b5f6ba6556bd9605e88227ea79e43d94e Mon Sep 17 00:00:00 2001
From: Teravus Ovares
Date: Fri, 25 Apr 2008 01:00:55 +0000
Subject: * Implements llTarget, llTargetRemove, at_target(), not_at_target()

---
 OpenSim/Region/Environment/Scenes/Scene.cs         |  11 ++
 OpenSim/Region/Environment/Scenes/SceneEvents.cs   |  30 +++-
 .../Region/Environment/Scenes/SceneObjectGroup.cs  | 152 ++++++++++++++++++++-
 .../Region/Environment/Scenes/SceneObjectPart.cs   |  16 ++-
 .../ScriptEngine/Common/LSL_BuiltIn_Commands.cs    |   6 +-
 .../Common/ScriptEngineBase/EventManager.cs        |  11 +-
 .../ScriptEngine/Common/ScriptServerInterfaces.cs  |   4 +-
 .../DotNetEngine/Compiler/LSL/LSL2CSConverter.cs   |  10 +-
 8 files changed, 221 insertions(+), 19 deletions(-)

(limited to 'OpenSim')

diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
index 21c8991..ae914b3 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.cs
@@ -2772,6 +2772,17 @@ namespace OpenSim.Region.Environment.Scenes
             m_eventManager.TriggerOnScriptChangedEvent(localID, change);
         }
 
+        public void TriggerAtTargetEvent(uint localID, uint handle, LLVector3 targetpos, LLVector3 currentpos)
+        {
+
+            m_eventManager.TriggerAtTargetEvent(localID, handle, targetpos, currentpos);
+        }
+
+        public void TriggerNotAtTargetEvent(uint localID)
+        {
+            m_eventManager.TriggerNotAtTargetEvent(localID);
+        }
+
         private bool scriptDanger(SceneObjectPart part,LLVector3 pos)
         {
             ILandObject parcel = LandChannel.getLandObject(pos.X, pos.Y);
diff --git a/OpenSim/Region/Environment/Scenes/SceneEvents.cs b/OpenSim/Region/Environment/Scenes/SceneEvents.cs
index c9c0ad6..74554c3 100644
--- a/OpenSim/Region/Environment/Scenes/SceneEvents.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneEvents.cs
@@ -132,9 +132,17 @@ namespace OpenSim.Region.Environment.Scenes
         public event ClientClosed OnClientClosed;
 
         public delegate void ScriptChangedEvent(uint localID, uint change);
-       
+
         public event ScriptChangedEvent OnScriptChangedEvent;
 
+        public delegate void ScriptAtTargetEvent(uint localID, uint handle, LLVector3 targetpos, LLVector3 atpos);
+
+        public event ScriptAtTargetEvent OnScriptAtTargetEvent;
+
+        public delegate void ScriptNotAtTargetEvent(uint localID);
+
+        public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent;
+
         public event OnNewPresenceDelegate OnMakeChildAgent;
 
         public delegate void NewInventoryItemUploadComplete(LLUUID avatarID, LLUUID assetID, string name, int userlevel);
@@ -224,6 +232,8 @@ namespace OpenSim.Region.Environment.Scenes
         /* Designated Event Deletage Instances */
 
         private ScriptChangedEvent handlerScriptChangedEvent = null; //OnScriptChangedEvent;
+        private ScriptAtTargetEvent handlerScriptAtTargetEvent = null;
+        private ScriptNotAtTargetEvent handlerScriptNotAtTargetEvent = null;
         private ClientMovement handlerClientMovement = null; //OnClientMovement;
         private OnPermissionErrorDelegate handlerPermissionError = null; //OnPermissionError;
         private OnPluginConsoleDelegate handlerPluginConsole = null; //OnPluginConsole;
@@ -534,5 +544,23 @@ namespace OpenSim.Region.Environment.Scenes
                 handlerValidateLandBuy(sender, e);
             }
         }
+        
+        public void TriggerAtTargetEvent(uint localID, uint handle, LLVector3 targetpos, LLVector3 currentpos)
+        {
+            handlerScriptAtTargetEvent = OnScriptAtTargetEvent;
+            if (handlerScriptAtTargetEvent != null)
+            {
+                handlerScriptAtTargetEvent(localID, handle, targetpos, currentpos);
+            }
+        }
+
+        public void TriggerNotAtTargetEvent(uint localID)
+        {
+            handlerScriptNotAtTargetEvent = OnScriptNotAtTargetEvent;
+            if (handlerScriptNotAtTargetEvent != null)
+            {
+                handlerScriptNotAtTargetEvent(localID);
+            }
+        }
     }
 }
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
index 27639ea..bd75e6f 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Region.Environment.Scenes
         land_collision = 2048,
         land_collision_end = 4096,
         land_collision_start = 8192,
-        link_message = 16384,
+        at_target = 16384,
         listen = 32768,
         money = 65536,
         moving_end = 131072,
@@ -72,6 +72,12 @@ namespace OpenSim.Region.Environment.Scenes
         object_rez = 4194304
     }
 
+    struct scriptPosTarget
+    {
+        public LLVector3 targetPos;
+        public float tolerance;
+    }
+
     public delegate void PrimCountTaintedDelegate();
 
     public partial class SceneObjectGroup : EntityBase
@@ -99,6 +105,12 @@ namespace OpenSim.Region.Environment.Scenes
         protected SceneObjectPart m_rootPart;
         private Dictionary<LLUUID, scriptEvents> m_scriptEvents = new Dictionary<LLUUID, scriptEvents>();
 
+        private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>();
+
+        private bool m_scriptListens_atTarget = false;
+        private bool m_scriptListens_notAtTarget = false;
+
+
         #region Properties
 
         /// <summary>
@@ -175,6 +187,8 @@ namespace OpenSim.Region.Environment.Scenes
                         string.Format("[SCENE OBJECT GROUP]: Object {0} has no root part.", m_uuid));
                 }
 
+                
+
                 return m_rootPart.GroupPosition;
             }
             set
@@ -193,6 +207,7 @@ namespace OpenSim.Region.Environment.Scenes
                         part.GroupPosition = val;
                     }
                 }
+                
                 //if (m_rootPart.PhysActor != null)
                 //{
                 //m_rootPart.PhysActor.Position =
@@ -202,7 +217,7 @@ namespace OpenSim.Region.Environment.Scenes
                 //}
             }
         }
-
+        
         public override uint LocalId
         {
             get
@@ -928,6 +943,33 @@ namespace OpenSim.Region.Environment.Scenes
                     part.ObjectFlags = objectflagupdate;
                 }
             }
+
+            if ((m_aggregateScriptEvents & scriptEvents.at_target) != 0)
+            {
+                m_scriptListens_atTarget = true;
+            }
+            else
+            {
+                m_scriptListens_atTarget = false;
+            }
+
+            if ((m_aggregateScriptEvents & scriptEvents.not_at_target) != 0)
+            {
+                m_scriptListens_notAtTarget = true;
+            }
+            else
+            {
+                m_scriptListens_notAtTarget = false;
+            }
+
+            if (m_scriptListens_atTarget || m_scriptListens_notAtTarget)
+            {
+            }
+            else
+            {
+                lock (m_targets)
+                    m_targets.Clear();
+            }
             ScheduleGroupForFullUpdate();
         }
 
@@ -1336,6 +1378,7 @@ namespace OpenSim.Region.Environment.Scenes
         /// </summary>
         public override void Update()
         {
+            
             lock (m_parts)
             {
                 if (Util.GetDistanceTo(lastPhysGroupPos, AbsolutePosition) > 0.02)
@@ -1346,6 +1389,7 @@ namespace OpenSim.Region.Environment.Scenes
                     }
 
                     lastPhysGroupPos = AbsolutePosition;
+                    checkAtTargets();
                 }
 
                 if ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1)
@@ -1396,7 +1440,7 @@ namespace OpenSim.Region.Environment.Scenes
         public void ScheduleGroupForFullUpdate()
         {
             HasGroupChanged = true;
-
+            checkAtTargets();
             lock (m_parts)
             {
                 foreach (SceneObjectPart part in m_parts.Values)
@@ -2301,5 +2345,107 @@ namespace OpenSim.Region.Environment.Scenes
 
             }
         }
+
+        public int registerTargetWaypoint(LLVector3 target, float tolerance)
+        {
+            scriptPosTarget waypoint = new scriptPosTarget();
+            waypoint.targetPos = target;
+            waypoint.tolerance = tolerance;
+            uint handle = m_scene.PrimIDAllocate();
+            lock (m_targets)
+            {
+                m_targets.Add(handle, waypoint);
+            }
+            return (int)handle;
+        }
+        public void unregisterTargetWaypoint(int handle)
+        {
+            lock (m_targets)
+            {
+                if (m_targets.ContainsKey((uint)handle))
+                    m_targets.Remove((uint)handle);
+            }
+        }
+
+        private void checkAtTargets()
+        {
+            if (m_scriptListens_atTarget || m_scriptListens_notAtTarget)
+            {
+                if (m_targets.Count > 0)
+                {
+                    bool at_target = false;
+                    //LLVector3 targetPos;
+                    //uint targetHandle;
+                    Dictionary<uint, scriptPosTarget> atTargets = new Dictionary<uint, scriptPosTarget>();
+                    lock (m_targets)
+                    {
+                        foreach (uint idx in m_targets.Keys)
+                        {
+                            scriptPosTarget target = m_targets[idx];
+                            if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance)
+                            {
+                                // trigger at_target
+                                if (m_scriptListens_atTarget)
+                                {
+                                    // Reusing att.tolerance to hold the index of the target in the targets dictionary
+                                    // to avoid deadlocking the sim.
+                                    at_target = true;
+                                    scriptPosTarget att = new scriptPosTarget();
+                                    att.targetPos = target.targetPos;
+                                    att.tolerance = (float)idx;
+                                    atTargets.Add(idx, att);
+                                }
+                            }
+                        }
+                    }
+                    if (atTargets.Count > 0)
+                    {
+                        uint[] localids = new uint[0];
+                        lock (m_parts)
+                        {
+                            localids = new uint[m_parts.Count];
+                            int cntr = 0;
+                            foreach (SceneObjectPart part in m_parts.Values)
+                            {
+                                localids[cntr] = part.LocalId;
+                                cntr++;
+                            }
+                        }
+                        for (int ctr = 0; ctr < localids.Length; ctr++)
+                        {
+                            foreach (uint target in atTargets.Keys)
+                            {
+                                scriptPosTarget att = atTargets[target];
+                                // Reusing att.tolerance to hold the index of the target in the targets dictionary
+                                // to avoid deadlocking the sim.
+                                m_scene.TriggerAtTargetEvent(localids[ctr], (uint)att.tolerance, att.targetPos, m_rootPart.GroupPosition);
+                                
+
+                            }
+                        }
+                        return;
+                    }
+                    if (m_scriptListens_notAtTarget && !at_target)
+                    {
+                        //trigger not_at_target
+                        uint[] localids = new uint[0];
+                        lock (m_parts)
+                        {
+                            localids = new uint[m_parts.Count];
+                            int cntr = 0;
+                            foreach (SceneObjectPart part in m_parts.Values)
+                            {
+                                localids[cntr] = part.LocalId;
+                                cntr++;
+                            }
+                        }
+                        for (int ctr = 0; ctr < localids.Length; ctr++)
+                        {
+                            m_scene.TriggerNotAtTargetEvent(localids[ctr]);
+                        }
+                    }
+                }
+            }
+        }
     }
 }
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
index 0608fa7..f345dab 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
@@ -2367,7 +2367,21 @@ namespace OpenSim.Region.Environment.Scenes
                 m_parentGroup.SetScriptEvents(scriptID, events);
             }
         }
-
+        public int registerTargetWaypoint(LLVector3 target, float tolerance)
+        {
+            if (m_parentGroup != null)
+            {
+                return m_parentGroup.registerTargetWaypoint(target, tolerance);
+            }
+            return 0;
+        }
+        public void unregisterTargetWaypoint(int handle)
+        {
+            if (m_parentGroup != null)
+            {
+                m_parentGroup.unregisterTargetWaypoint(handle);
+            }
+        }
         protected SceneObjectPart(SerializationInfo info, StreamingContext context)
         {
             //System.Console.WriteLine("SceneObjectPart Deserialize BGN");
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
index 35f8ee0..79b13cf 100644
--- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
+++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
@@ -1181,14 +1181,14 @@ namespace OpenSim.Region.ScriptEngine.Common
         public int llTarget(LSL_Types.Vector3 position, double range)
         {
             m_host.AddScriptLPS(1);
-            NotImplemented("llTarget");
-            return 0;
+            return m_host.registerTargetWaypoint(new LLVector3((float)position.x, (float)position.y, (float)position.z), (float)range);
+           
         }
 
         public void llTargetRemove(int number)
         {
             m_host.AddScriptLPS(1);
-            NotImplemented("llTargetRemove");
+            m_host.unregisterTargetWaypoint(number);
         }
 
         public int llRotTarget(LSL_Types.Quaternion rot, double error)
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
index d3e9948..ce9f445 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
@@ -70,6 +70,9 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
                 myScriptEngine.World.EventManager.OnRezScript += OnRezScript;
                 myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript;
                 myScriptEngine.World.EventManager.OnScriptChangedEvent += changed;
+                myScriptEngine.World.EventManager.OnScriptAtTargetEvent += at_target;
+                myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target;
+
                 // TODO: HOOK ALL EVENTS UP TO SERVER!
                 IMoneyModule money=myScriptEngine.World.RequestModuleInterface<IMoneyModule>();
                 if(money != null)
@@ -222,14 +225,14 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
             myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "email", EventQueueManager.llDetectNull);
         }
 
-        public void at_target(uint localID, LLUUID itemID)
+        public void at_target(uint localID, uint handle, LLVector3 targetpos, LLVector3 atpos)
         {
-            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_target", EventQueueManager.llDetectNull);
+            myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "at_target", EventQueueManager.llDetectNull, new object[] { (int)handle, new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) });
         }
 
-        public void not_at_target(uint localID, LLUUID itemID)
+        public void not_at_target(uint localID)
         {
-            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_target", EventQueueManager.llDetectNull);
+            myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "not_at_target", EventQueueManager.llDetectNull);
         }
 
         public void at_rot_target(uint localID, LLUUID itemID)
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs b/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs
index ea17e20..1c85646 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs
@@ -57,8 +57,8 @@ namespace OpenSim.Region.ScriptEngine.Common
             void control(uint localID, LLUUID itemID);
             void money(uint LocalID, LLUUID agentID, int amount);
             void email(uint localID, LLUUID itemID);
-            void at_target(uint localID, LLUUID itemID);
-            void not_at_target(uint localID, LLUUID itemID);
+            void at_target(uint localID, uint handle, LLVector3 targetpos, LLVector3 atpos);
+            void not_at_target(uint localID);
             void at_rot_target(uint localID, LLUUID itemID);
             void not_at_rot_target(uint localID, LLUUID itemID);
             void run_time_permissions(uint localID, LLUUID itemID);
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs
index 50bc892..a766ea2 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs
@@ -419,8 +419,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
                // case "at_rot_target":
                     //return (long)scriptEvents.at_rot_target;
                     //break;
-                //case "at_target":
-                    //return (long)scriptEvents.at_target;
+                case "at_target":
+                    return scriptEvents.at_target;
                     //break;
                 //case "changed":
                     //return (long)scriptEvents.changed;
@@ -455,8 +455,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
                 case "land_collision_start":
                     return scriptEvents.land_collision_start;
                    // break;
-                case "link_message":
-                    return scriptEvents.link_message;
+                //case "link_message":
+                    //return scriptEvents.link_message;
                   //  break;
                 case "listen":
                     return scriptEvents.listen;
@@ -534,7 +534,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
         land_collision = 2048,
         land_collision_end = 4096,
         land_collision_start = 8192,
-        link_message = 16384,
+        at_target = 16384,
         listen = 32768,
         money = 65536,
         moving_end = 131072,
-- 
cgit v1.1