From e12baa5eb33882fc1d4c6aa0886037e00d726e2e Mon Sep 17 00:00:00 2001
From: Teravus Ovares
Date: Thu, 5 Jun 2008 13:24:59 +0000
Subject: * This sends collision events to the script engine. * Unfortunately,
 there's some kludges with the Async manager and the llDetected functions that
 I have yet to decipher...  so llDetected functions don't work with collision
 events at the moment....

---
 OpenSim/Framework/ColliderData.cs                  |  54 ++++++
 OpenSim/Region/Environment/Scenes/EventManager.cs  |  38 ++++-
 .../Region/Environment/Scenes/SceneObjectPart.cs   | 186 +++++++++++++++++++--
 .../ScriptEngine/Common/LSL_BuiltIn_Commands.cs    |  55 +++++-
 .../Common/ScriptEngineBase/EventManager.cs        |  85 +++++++++-
 .../Common/ScriptEngineBase/EventQueueManager.cs   |   3 +-
 .../ScriptEngine/Common/ScriptServerInterfaces.cs  |   9 +-
 7 files changed, 402 insertions(+), 28 deletions(-)
 create mode 100644 OpenSim/Framework/ColliderData.cs

diff --git a/OpenSim/Framework/ColliderData.cs b/OpenSim/Framework/ColliderData.cs
new file mode 100644
index 0000000..075a4e0
--- /dev/null
+++ b/OpenSim/Framework/ColliderData.cs
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the OpenSim Project nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections;
+using libsecondlife;
+using System.Collections.Generic;
+
+namespace OpenSim.Framework
+{
+    public class DetectedObject
+    {
+        public DetectedObject() { }
+        public LLUUID groupUUID = LLUUID.Zero;
+        public LLUUID ownerUUID = LLUUID.Zero;
+        public LLUUID keyUUID = LLUUID.Zero;
+        public LLVector3 posVector = LLVector3.Zero;
+        public LLQuaternion rotQuat = LLQuaternion.Identity;
+        public LLVector3 velVector = LLVector3.Zero;
+        public string nameStr = String.Empty;
+        public int colliderType = 0;
+    }
+
+    public class ColliderArgs : EventArgs
+    {
+        public ColliderArgs() { }
+        public List<DetectedObject> Colliders = new List<DetectedObject>();
+
+    }
+}
diff --git a/OpenSim/Region/Environment/Scenes/EventManager.cs b/OpenSim/Region/Environment/Scenes/EventManager.cs
index eee4e4a..5c750e4 100644
--- a/OpenSim/Region/Environment/Scenes/EventManager.cs
+++ b/OpenSim/Region/Environment/Scenes/EventManager.cs
@@ -158,9 +158,17 @@ namespace OpenSim.Region.Environment.Scenes
         public event ScriptAtTargetEvent OnScriptAtTargetEvent;
 
         public delegate void ScriptNotAtTargetEvent(uint localID);
-
+        
         public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent;
 
+        public delegate void ScriptColliding(uint localID, ColliderArgs colliders);
+
+        public event ScriptColliding OnScriptColliderStart;
+        public event ScriptColliding OnScriptColliding;
+        public event ScriptColliding OnScriptCollidingEnd;
+
+        
+
         public delegate void OnMakeChildAgentDelegate(ScenePresence presence);
         public event OnMakeChildAgentDelegate OnMakeChildAgent;
 
@@ -293,6 +301,8 @@ namespace OpenSim.Region.Environment.Scenes
             }
         }
 
+
+
         public delegate void MoneyTransferEvent(Object sender, MoneyTransferArgs e);
 
         public delegate void LandBuy(Object sender, LandBuyArgs e);
@@ -357,6 +367,11 @@ namespace OpenSim.Region.Environment.Scenes
         private ScriptTimerEvent handlerScriptTimerEvent = null;
         private EstateToolsTimeUpdate handlerEstateToolsTimeUpdate = null;
 
+        private ScriptColliding handlerCollidingStart = null;
+        private ScriptColliding handlerColliding = null;
+        private ScriptColliding handlerCollidingEnd = null;
+
+
         private SunLindenHour handlerSunGetLindenHour = null;
 
         public void TriggerOnScriptChangedEvent(uint localID, uint change)
@@ -838,5 +853,26 @@ namespace OpenSim.Region.Environment.Scenes
             }
             return 6;
         }
+
+        public void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
+        {
+            handlerCollidingStart = OnScriptColliderStart;
+            if (handlerCollidingStart != null)
+                handlerCollidingStart(localId, colliders);
+        }
+        public void TriggerScriptColliding(uint localId, ColliderArgs colliders)
+        {
+
+            handlerColliding = OnScriptColliding;
+            if (handlerColliding != null)
+                handlerColliding(localId, colliders);
+        }
+        public void TriggerScriptCollidingEnd(uint localId, ColliderArgs colliders)
+        {
+            handlerCollidingEnd = OnScriptCollidingEnd;
+            if (handlerCollidingEnd != null)
+                handlerCollidingEnd(localId, colliders);
+        }
+
     }
 }
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
index ce7497d..532d003 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
@@ -113,6 +113,8 @@ namespace OpenSim.Region.Environment.Scenes
         public Int32 CreationDate;
         public uint ParentID = 0;
 
+        private List<uint> m_lastColliders = new List<uint>();
+
         private PhysicsVector m_lastRotationalVelocity = PhysicsVector.Zero;
         private Vector3 m_sitTargetPosition = new Vector3(0, 0, 0);
         private Quaternion m_sitTargetOrientation = new Quaternion(0, 0, 0, 1);
@@ -2807,21 +2809,181 @@ namespace OpenSim.Region.Environment.Scenes
         }
         public void PhysicsCollision(EventArgs e)
         {
-            return;
+            //return;
 
-            //
-            //if (e == null)
-            //{
-            //    return;
-            //}
-            //CollisionEventUpdate a = (CollisionEventUpdate)e;
-            //Dictionary<uint, float> collissionswith = a.m_objCollisionList;
-            //foreach (uint localid in collissionswith.Keys)
-            //{
-             //   m_log.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
-            //}
+            // single threaded here
+            if (e == null)
+            {
+                return;
+            }
+            
+            CollisionEventUpdate a = (CollisionEventUpdate)e;
+            Dictionary<uint, float> collissionswith = a.m_objCollisionList;
+            List<uint> thisHitColliders = new List<uint>();
+            List<uint> endedColliders = new List<uint>();
+            List<uint> startedColliders = new List<uint>();
+
+            // calculate things that started colliding this time
+            // and build up list of colliders this time
+            foreach (uint localid in collissionswith.Keys)
+            {
+                if (localid != 0)
+                {
+                    thisHitColliders.Add(localid);
+                    if (!m_lastColliders.Contains(localid))
+                    {
+                        startedColliders.Add(localid);
+                    }
+
+
+                    //m_log.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
+                }
+            }
+
+            // calculate things that ended colliding
+            foreach (uint localID in m_lastColliders)
+            {
+                if (!thisHitColliders.Contains(localID))
+                {
+                    endedColliders.Add(localID);
+                }
+            }
+            // remove things that ended colliding from the last colliders list
+            foreach (uint localID in endedColliders)
+            {
+                m_lastColliders.Remove(localID);
+            }
+
+            //add the items that started colliding this time to the last colliders list.
+            foreach (uint localID in startedColliders)
+            {
+                m_lastColliders.Add(localID);
+            }
+            // do event notification
+            if (startedColliders.Count > 0)
+            {
+                ColliderArgs StartCollidingMessage = new ColliderArgs();
+                List<DetectedObject> colliding = new List<DetectedObject>();
+                foreach (uint localId in startedColliders)
+                {
+                    // always running this check because if the user deletes the object it would return a null reference.
+                    if (m_parentGroup == null)
+                        return;
+                    if (m_parentGroup.Scene == null)
+                        return;
+                    SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
+                    if (obj != null)
+                    {
+                        DetectedObject detobj = new DetectedObject();
+                        detobj.keyUUID = obj.UUID;
+                        detobj.nameStr = obj.Name;
+                        detobj.ownerUUID = obj.OwnerID;
+                        detobj.posVector = obj.AbsolutePosition;
+                        detobj.rotQuat = obj.GetWorldRotation();
+                        detobj.velVector = obj.Velocity;
+                        detobj.colliderType = 0;
+                        detobj.groupUUID = obj.GroupID;
+                        colliding.Add(detobj);
+                    }
+                }
+                if (colliding.Count > 0)
+                {
+                    StartCollidingMessage.Colliders = colliding;
+                    // always running this check because if the user deletes the object it would return a null reference.
+                    if (m_parentGroup == null)
+                        return;
+                    if (m_parentGroup.Scene == null)
+                        return;
+                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(LocalId, StartCollidingMessage);
+                }
+
+            }
+            if (m_lastColliders.Count > 0)
+            {
+                ColliderArgs CollidingMessage = new ColliderArgs();
+                List<DetectedObject> colliding = new List<DetectedObject>();
+                foreach (uint localId in m_lastColliders)
+                {
+                    // always running this check because if the user deletes the object it would return a null reference.
+                    if (localId == 0)
+                        continue;
+
+                    if (m_parentGroup == null)
+                        return;
+                    if (m_parentGroup.Scene == null)
+                        return;
+                    SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
+                    if (obj != null)
+                    {
+                        DetectedObject detobj = new DetectedObject();
+                        detobj.keyUUID = obj.UUID;
+                        detobj.nameStr = obj.Name;
+                        detobj.ownerUUID = obj.OwnerID;
+                        detobj.posVector = obj.AbsolutePosition;
+                        detobj.rotQuat = obj.GetWorldRotation();
+                        detobj.velVector = obj.Velocity;
+                        detobj.colliderType = 0;
+                        detobj.groupUUID = obj.GroupID;
+                        colliding.Add(detobj);
+                    }
+                }
+                if (colliding.Count > 0)
+                {
+                    CollidingMessage.Colliders = colliding;
+                    // always running this check because if the user deletes the object it would return a null reference.
+                    if (m_parentGroup == null)
+                        return;
+                    if (m_parentGroup.Scene == null)
+                        return;
+                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(LocalId, CollidingMessage);
+                }
+
+            }
+            if (endedColliders.Count > 0)
+            {
+                ColliderArgs EndCollidingMessage = new ColliderArgs();
+                List<DetectedObject> colliding = new List<DetectedObject>();
+                foreach (uint localId in endedColliders)
+                {
+                    if (localId == 0)
+                        continue;
+
+                    // always running this check because if the user deletes the object it would return a null reference.
+                    if (m_parentGroup == null)
+                        return;
+                    if (m_parentGroup.Scene == null)
+                        return;
+                    SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
+                    if (obj != null)
+                    {
+                        DetectedObject detobj = new DetectedObject();
+                        detobj.keyUUID = obj.UUID;
+                        detobj.nameStr = obj.Name;
+                        detobj.ownerUUID = obj.OwnerID;
+                        detobj.posVector = obj.AbsolutePosition;
+                        detobj.rotQuat = obj.GetWorldRotation();
+                        detobj.velVector = obj.Velocity;
+                        detobj.colliderType = 0;
+                        detobj.groupUUID = obj.GroupID;
+                        colliding.Add(detobj);
+                    }
+                }
+                if (colliding.Count > 0)
+                {
+                    EndCollidingMessage.Colliders = colliding;
+                    // always running this check because if the user deletes the object it would return a null reference.
+                    if (m_parentGroup == null)
+                        return;
+                    if (m_parentGroup.Scene == null)
+                        return;
+                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(LocalId, EndCollidingMessage);
+                }
+
+            }
         }
 
+
+
         public void SetDieAtEdge(bool p)
         {
             if (m_parentGroup == null)
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
index 663ac0c..4c58e36 100644
--- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
+++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
@@ -562,6 +562,25 @@ namespace OpenSim.Region.ScriptEngine.Common
                     return resolveName(SensedUUID);
                 }
             }
+            else
+            {
+                ScriptManager sm;
+                IScript script = null;
+
+                if ((sm = m_ScriptEngine.m_ScriptManager) != null)
+                {
+                    if (sm.Scripts.ContainsKey(m_localID))
+                    {
+                        if ((script = sm.GetScript(m_localID, m_itemID)) != null)
+                        {
+                            if (script.llDetectParams._bool.Length > number && script.llDetectParams._bool[number])
+                            {
+                                return script.llDetectParams._string[number];
+                            }
+                        }
+                    }
+                }
+            }
             return String.Empty;
        }
 
@@ -587,9 +606,12 @@ namespace OpenSim.Region.ScriptEngine.Common
                     {
                         if ((script = sm.GetScript(m_localID, m_itemID)) != null)
                         {
-                            if (script.llDetectParams._key[0])
+                            if (script.llDetectParams._bool.Length > number && script.llDetectParams._bool[number])
                             {
-                                return new LLUUID(script.llDetectParams._key[0]);
+                                LLUUID returnUUID = LLUUID.Zero;
+                                Helpers.TryParse(script.llDetectParams._key[number], out returnUUID);
+
+                                return returnUUID;
                             }
                         }
                     }
@@ -614,6 +636,35 @@ namespace OpenSim.Region.ScriptEngine.Common
                     return SensedObject;
                 }
             }
+            else
+            {
+                ScriptManager sm;
+                IScript script = null;
+
+                if ((sm = m_ScriptEngine.m_ScriptManager) != null)
+                {
+                    if (sm.Scripts.ContainsKey(m_localID))
+                    {
+                        if ((script = sm.GetScript(m_localID, m_itemID)) != null)
+                        {
+                            if (script.llDetectParams._key[number])
+                            {
+                                EntityBase SensedObject = null;
+                                LLUUID SensedUUID = LLUUID.Zero;
+                                Helpers.TryParse(script.llDetectParams._key.ToString(), out SensedUUID);
+                                if (SensedUUID == LLUUID.Zero)
+                                    return null;
+                                lock (World.Entities)
+                                {
+                                    World.Entities.TryGetValue(SensedUUID, out SensedObject);
+                                }
+                                return SensedObject;
+                                
+                            }
+                        }
+                    }
+                }
+            }
             return null;
         }
 
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
index 5ef4a6b..ae84f65 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
@@ -26,9 +26,12 @@
  */
 
 using System;
+using System.Collections.Generic;
 using libsecondlife;
 using OpenSim.Framework;
 using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney;
+using OpenSim.Region.Environment;
+using OpenSim.Region;
 using OpenSim.Region.Environment.Scenes;
 using OpenSim.Region.Environment.Interfaces;
 
@@ -74,6 +77,9 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
                 myScriptEngine.World.EventManager.OnScriptAtTargetEvent += at_target;
                 myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target;
                 myScriptEngine.World.EventManager.OnScriptControlEvent += control;
+                myScriptEngine.World.EventManager.OnScriptColliderStart += collision_start;
+                myScriptEngine.World.EventManager.OnScriptColliding += collision;
+                myScriptEngine.World.EventManager.OnScriptCollidingEnd += collision_end;
 
                 // TODO: HOOK ALL EVENTS UP TO SERVER!
                 IMoneyModule money=myScriptEngine.World.RequestModuleInterface<IMoneyModule>();
@@ -171,19 +177,82 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
             myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch_end", EventQueueManager.llDetectNull, new object[] { new LSL_Types.LSLInteger(1) });
         }
 
-        public void collision_start(uint localID, LLUUID itemID)
+        public void collision_start(uint localID, ColliderArgs col)
         {
-            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_start", EventQueueManager.llDetectNull, new object[] { new LSL_Types.LSLInteger(1) });
+            EventQueueManager.Queue_llDetectParams_Struct detstruct = new EventQueueManager.Queue_llDetectParams_Struct();
+            detstruct._string = new string[col.Colliders.Count];
+            detstruct._Quaternion = new LSL_Types.Quaternion[col.Colliders.Count];
+            detstruct._int = new int[col.Colliders.Count];
+            detstruct._key = new LSL_Types.key[col.Colliders.Count];
+            detstruct._Vector3 = new LSL_Types.Vector3[col.Colliders.Count];
+            detstruct._Vector32 = new LSL_Types.Vector3[col.Colliders.Count];
+            detstruct._bool = new bool[col.Colliders.Count];
+
+            int i = 0;
+            foreach (DetectedObject detobj in col.Colliders)
+            {
+                detstruct._key[i] = new LSL_Types.key(detobj.keyUUID.ToString());
+                detstruct._Quaternion[i] = new LSL_Types.Quaternion(detobj.rotQuat.X, detobj.rotQuat.Y, detobj.rotQuat.Z, detobj.rotQuat.W);
+                detstruct._string[i] = detobj.nameStr;
+                detstruct._int[i] = detobj.colliderType;
+                detstruct._Vector3[i] = new LSL_Types.Vector3(detobj.posVector.X, detobj.posVector.Y, detobj.posVector.Z);
+                detstruct._Vector32[i] = new LSL_Types.Vector3(detobj.velVector.X, detobj.velVector.Y, detobj.velVector.Z);
+                detstruct._bool[i] = true; // Apparently the script engine uses this to see if this is a valid entry...       
+                i++;
+            }
+
+            myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "collision_start", detstruct, new object[] { new LSL_Types.LSLInteger(col.Colliders.Count) });
         }
 
-        public void collision(uint localID, LLUUID itemID)
+        public void collision(uint localID, ColliderArgs col)
         {
-            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision", EventQueueManager.llDetectNull, new object[] { new LSL_Types.LSLInteger(1) });
+            EventQueueManager.Queue_llDetectParams_Struct detstruct = new EventQueueManager.Queue_llDetectParams_Struct();
+            detstruct._string = new string[col.Colliders.Count];
+            detstruct._Quaternion = new LSL_Types.Quaternion[col.Colliders.Count];
+            detstruct._int = new int[col.Colliders.Count];
+            detstruct._key = new LSL_Types.key[col.Colliders.Count];
+            detstruct._Vector3 = new LSL_Types.Vector3[col.Colliders.Count];
+            detstruct._Vector32 = new LSL_Types.Vector3[col.Colliders.Count];
+            detstruct._bool = new bool[col.Colliders.Count];
+
+            int i = 0;
+            foreach (DetectedObject detobj in col.Colliders)
+            {
+                detstruct._key[i] = new LSL_Types.key(detobj.keyUUID.ToString());
+                detstruct._Quaternion[i] = new LSL_Types.Quaternion(detobj.rotQuat.X, detobj.rotQuat.Y, detobj.rotQuat.Z, detobj.rotQuat.W);
+                detstruct._string[i] = detobj.nameStr;
+                detstruct._int[i] = detobj.colliderType;
+                detstruct._Vector3[i] = new LSL_Types.Vector3(detobj.posVector.X, detobj.posVector.Y, detobj.posVector.Z);
+                detstruct._Vector32[i] = new LSL_Types.Vector3(detobj.velVector.X, detobj.velVector.Y, detobj.velVector.Z);
+                detstruct._bool[i] = true; // Apparently the script engine uses this to see if this is a valid entry...                    i++;
+            }
+            myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "collision", detstruct, new object[] { new LSL_Types.LSLInteger(col.Colliders.Count) });
         }
 
-        public void collision_end(uint localID, LLUUID itemID)
+        public void collision_end(uint localID, ColliderArgs col)
         {
-            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_end", EventQueueManager.llDetectNull, new object[] { new LSL_Types.LSLInteger(1) });
+            EventQueueManager.Queue_llDetectParams_Struct detstruct = new EventQueueManager.Queue_llDetectParams_Struct();
+            detstruct._string = new string[col.Colliders.Count];
+            detstruct._Quaternion = new LSL_Types.Quaternion[col.Colliders.Count];
+            detstruct._int = new int[col.Colliders.Count];
+            detstruct._key = new LSL_Types.key[col.Colliders.Count];
+            detstruct._Vector3 = new LSL_Types.Vector3[col.Colliders.Count];
+            detstruct._Vector32 = new LSL_Types.Vector3[col.Colliders.Count];
+            detstruct._bool = new bool[col.Colliders.Count];
+
+            int i = 0;
+            foreach (DetectedObject detobj in col.Colliders)
+            {
+                detstruct._key[i] = new LSL_Types.key(detobj.keyUUID.ToString());
+                detstruct._Quaternion[i] = new LSL_Types.Quaternion(detobj.rotQuat.X, detobj.rotQuat.Y, detobj.rotQuat.Z, detobj.rotQuat.W);
+                detstruct._string[i] = detobj.nameStr;
+                detstruct._int[i] = detobj.colliderType;
+                detstruct._Vector3[i] = new LSL_Types.Vector3(detobj.posVector.X, detobj.posVector.Y, detobj.posVector.Z);
+                detstruct._Vector32[i] = new LSL_Types.Vector3(detobj.velVector.X, detobj.velVector.Y, detobj.velVector.Z);
+                detstruct._bool[i] = true; // Apparently the script engine uses this to see if this is a valid entry...       
+                i++;
+            }
+            myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "collision_end", EventQueueManager.llDetectNull, new object[] { new LSL_Types.LSLInteger(col.Colliders.Count) });
         }
 
         public void land_collision_start(uint localID, LLUUID itemID)
@@ -191,9 +260,9 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
             myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_start", EventQueueManager.llDetectNull);
         }
 
-        public void land_collision(uint localID, LLUUID itemID)
+        public void land_collision(uint localID, ColliderArgs col)
         {
-            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision", EventQueueManager.llDetectNull);
+            myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "land_collision", EventQueueManager.llDetectNull);
         }
 
         public void land_collision_end(uint localID, LLUUID itemID)
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
index 7cbbd4f..c6eebf1 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
@@ -155,7 +155,8 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
             // should be fixed to something better :)
             public LSL_Types.key[] _key;
             public LSL_Types.Quaternion[] _Quaternion;
-            public LSL_Types.Vector3[] _Vector3;
+            public LSL_Types.Vector3[] _Vector3; // Pos
+            public LSL_Types.Vector3[] _Vector32; // Vel
             public bool[] _bool;
             public int[] _int;
             public string[] _string;
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs b/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs
index be42539..59f828d 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs
@@ -31,6 +31,7 @@ using OpenSim.Framework;
 using OpenSim.Region.Environment.Scenes;
 using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase;
 
+
 namespace OpenSim.Region.ScriptEngine.Common
 {
     public class ScriptServerInterfaces
@@ -43,11 +44,11 @@ namespace OpenSim.Region.ScriptEngine.Common
             void state_exit(uint localID);
             void touch(uint localID, LLUUID itemID);
             void touch_end(uint localID, LLUUID itemID);
-            void collision_start(uint localID, LLUUID itemID);
-            void collision(uint localID, LLUUID itemID);
-            void collision_end(uint localID, LLUUID itemID);
+            void collision_start(uint localID, ColliderArgs col);
+            void collision(uint localID, ColliderArgs col);
+            void collision_end(uint localID, ColliderArgs col);
             void land_collision_start(uint localID, LLUUID itemID);
-            void land_collision(uint localID, LLUUID itemID);
+            void land_collision(uint localID, ColliderArgs col);
             void land_collision_end(uint localID, LLUUID itemID);
             void timer(uint localID, LLUUID itemID);
             void listen(uint localID, LLUUID itemID);
-- 
cgit v1.1