From 016a648a3097b452f63b82af533e92c549ce0ca6 Mon Sep 17 00:00:00 2001
From: Teravus Ovares (Dan Olivares)
Date: Fri, 4 Sep 2009 20:19:34 -0400
Subject: * Fixes various quirks rezzing in virtual regions. * Breaks up the
 Client event registrations in Scene into methods of similar event types.  
 The generic event registration registers all of the event types. *Created
 symmetrical Un-Registration methods. * Made the Registration and
 Unregistration methods public * Hooks The events required for creating new
 prim and rezzing new prim into the proper scene.

---
 .../CoreModules/World/Land/RegionCombinerModule.cs | 248 ++++++++++++++-----
 OpenSim/Region/Framework/Scenes/Scene.cs           | 268 ++++++++++++++++++---
 2 files changed, 434 insertions(+), 82 deletions(-)

(limited to 'OpenSim/Region')

diff --git a/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs b/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs
index 5c5f164..91d736b 100644
--- a/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs
@@ -32,6 +32,7 @@ using log4net;
 using Nini.Config;
 using OpenMetaverse;
 using OpenSim.Framework;
+using OpenSim.Framework.Client;
 using OpenSim.Region.Framework.Interfaces;
 using OpenSim.Region.Framework.Scenes;
 
@@ -71,6 +72,18 @@ namespace OpenSim.Region.CoreModules.World.Land
         public void AddRegion(Scene scene)
         {
            
+            
+            
+        }
+
+        public void RemoveRegion(Scene scene)
+        {
+           
+                
+        }
+
+        public void RegionLoaded(Scene scene)
+        {
             if (!enabledYN)
                 return;
 
@@ -295,8 +308,8 @@ namespace OpenSim.Region.CoreModules.World.Land
                         m_log.DebugFormat("Scene: {0} to the west of Scene{1} Offset: {2}. Extents:{3}",
                                           conn.RegionScene.RegionInfo.RegionName,
                                           regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
-                        
-                        
+
+
                         scene.BordersLocked = true;
                         conn.RegionScene.BordersLocked = true;
 
@@ -325,9 +338,11 @@ namespace OpenSim.Region.CoreModules.World.Land
                         //
                         scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
                         //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
-                        
+
                         conn.RegionScene.BordersLocked = false;
                         scene.BordersLocked = false;
+                        if (conn.ClientEventForwarder != null)
+                            conn.ClientEventForwarder.AddSceneToEventForwarding(scene);
                         connectedYN = true;
                         break;
                     }
@@ -367,7 +382,7 @@ namespace OpenSim.Region.CoreModules.World.Land
                         m_log.DebugFormat("Scene: {0} to the northeast of Scene{1} Offset: {2}. Extents:{3}",
                                          conn.RegionScene.RegionInfo.RegionName,
                                          regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
-                        conn.RegionScene.PhysicsScene.Combine(null,Vector3.Zero,extents);
+                        conn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
                         scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, Vector3.Zero);
 
                         lock (conn.RegionScene.NorthBorders)
@@ -386,7 +401,8 @@ namespace OpenSim.Region.CoreModules.World.Land
 
                         scene.BordersLocked = false;
                         conn.RegionScene.BordersLocked = false;
-
+                        if (conn.ClientEventForwarder != null)
+                            conn.ClientEventForwarder.AddSceneToEventForwarding(scene);
                         connectedYN = true;
                         break;
                     }
@@ -424,52 +440,52 @@ namespace OpenSim.Region.CoreModules.World.Land
                         m_log.DebugFormat("Scene: {0} to the NorthEast of Scene{1} Offset: {2}. Extents:{3}",
                                          conn.RegionScene.RegionInfo.RegionName,
                                          regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
-                        
+
                         conn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
                         scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, Vector3.Zero);
                         lock (conn.RegionScene.NorthBorders)
-                        if (conn.RegionScene.NorthBorders.Count == 1)// &&  2)
-                        {
-                            //compound border
-                            // already locked above
-                            conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
+                            if (conn.RegionScene.NorthBorders.Count == 1)// &&  2)
+                            {
+                                //compound border
+                                // already locked above
+                                conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
 
-                            lock (conn.RegionScene.EastBorders)
-                                conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-                            lock (conn.RegionScene.WestBorders)
-                                conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
+                                lock (conn.RegionScene.EastBorders)
+                                    conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
+                                lock (conn.RegionScene.WestBorders)
+                                    conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
 
-                            
 
-                        }
+
+                            }
                         lock (scene.SouthBorders)
                             scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south
-                        
+
                         lock (conn.RegionScene.EastBorders)
-                        if (conn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
-                        {
+                            if (conn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
+                            {
 
-                            conn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
-                            lock (conn.RegionScene.NorthBorders)
-                                conn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-                            lock (conn.RegionScene.SouthBorders)
-                                conn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
+                                conn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
+                                lock (conn.RegionScene.NorthBorders)
+                                    conn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
+                                lock (conn.RegionScene.SouthBorders)
+                                    conn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
 
-                            
-                        }
+
+                            }
 
                         lock (scene.WestBorders)
                             scene.WestBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport West
-/*  
-                        else
-                        {
-                            conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
-                            conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-                            conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-                            scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south
-                        }
-*/
-                        
+                        /*  
+                                                else
+                                                {
+                                                    conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
+                                                    conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
+                                                    conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
+                                                    scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south
+                                                }
+                        */
+
 
                         // Reset Terrain..  since terrain normally loads first.
                         //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
@@ -478,6 +494,9 @@ namespace OpenSim.Region.CoreModules.World.Land
                         scene.BordersLocked = false;
                         conn.RegionScene.BordersLocked = false;
 
+                        if (conn.ClientEventForwarder != null)
+                            conn.ClientEventForwarder.AddSceneToEventForwarding(scene);
+
                         connectedYN = true;
 
                         //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
@@ -495,7 +514,7 @@ namespace OpenSim.Region.CoreModules.World.Land
                     rdata.RegionScene = scene;
                     regionConnections.RegionLandChannel = scene.LandChannel;
 
-                    RegionCombinerLargeLandChannel lnd = new RegionCombinerLargeLandChannel(rdata,scene.LandChannel,regionConnections.ConnectedRegions);
+                    RegionCombinerLargeLandChannel lnd = new RegionCombinerLargeLandChannel(rdata, scene.LandChannel, regionConnections.ConnectedRegions);
                     scene.LandChannel = lnd;
                     lock (m_regions)
                     {
@@ -504,24 +523,14 @@ namespace OpenSim.Region.CoreModules.World.Land
                             ForwardPermissionRequests(regionConnections, r.RegionScene);
                         }
                     }
-                    
-                    m_regions.Add(scene.RegionInfo.originRegionID,regionConnections);
+
+                    regionConnections.ClientEventForwarder = new RegionCombinerClientEventForwarder(regionConnections);
+
+                    m_regions.Add(scene.RegionInfo.originRegionID, regionConnections);
                 }
-                    
+
             }
             AdjustLargeRegionBounds();
-            
-        }
-
-        public void RemoveRegion(Scene scene)
-        {
-           
-                
-        }
-
-        public void RegionLoaded(Scene scene)
-        {
-            
         }
 
         public void PostInitialise()
@@ -733,6 +742,7 @@ namespace OpenSim.Region.CoreModules.World.Land
         public int YEnd;
         public List<RegionData> ConnectedRegions;
         public RegionCombinerPermissionModule PermissionModule;
+        public RegionCombinerClientEventForwarder ClientEventForwarder;
         public void UpdateExtents(Vector3 extents)
         {
             XEnd = (int)extents.X;
@@ -790,7 +800,7 @@ namespace OpenSim.Region.CoreModules.World.Land
             else
             {
                 int offsetX = (x / (int)Constants.RegionSize);
-                int offsetY = (x / (int)Constants.RegionSize);
+                int offsetY = (y / (int)Constants.RegionSize);
                 offsetX *= (int)Constants.RegionSize;
                 offsetY *= (int)Constants.RegionSize;
 
@@ -823,7 +833,7 @@ namespace OpenSim.Region.CoreModules.World.Land
             else
             {
                 int offsetX = (int)(x/(int) Constants.RegionSize);
-                int offsetY = (int)(x/(int) Constants.RegionSize);
+                int offsetY = (int)(y/(int) Constants.RegionSize);
                 offsetX *= (int) Constants.RegionSize;
                 offsetY *= (int) Constants.RegionSize;
 
@@ -886,6 +896,7 @@ namespace OpenSim.Region.CoreModules.World.Land
             m_rootScene = RootScene;
         }
 
+        #region Permission Override
         public bool BypassPermissions()
         {
             return m_rootScene.Permissions.BypassPermissions();
@@ -1110,5 +1121,132 @@ namespace OpenSim.Region.CoreModules.World.Land
         {
             return m_rootScene.Permissions.CanUseObjectReturn(landdata, type, client, retlist);
         }
+        #endregion
+    }
+
+    public class RegionCombinerClientEventForwarder
+    {
+        private Scene m_rootScene;
+        private Dictionary<UUID, Scene> m_virtScene = new Dictionary<UUID, Scene>();
+        private Dictionary<UUID,RegionCombinerModuleIndividualForwarder> m_forwarders = new Dictionary<UUID, RegionCombinerModuleIndividualForwarder>();
+        public RegionCombinerClientEventForwarder(RegionConnections rootScene)
+        {
+            m_rootScene = rootScene.RegionScene;
+
+            
+        }
+
+        public void AddSceneToEventForwarding( Scene virtualScene )
+        {
+            lock (m_virtScene)
+            {
+                if (m_virtScene.ContainsKey(virtualScene.RegionInfo.originRegionID))
+                {
+                    m_virtScene[virtualScene.RegionInfo.originRegionID] = virtualScene;
+                }
+                else
+                {
+                    m_virtScene.Add(virtualScene.RegionInfo.originRegionID, virtualScene);
+                }
+            }
+            
+            lock (m_forwarders)
+            {
+                // TODO: Fix this to unregister if this happens
+                if (m_forwarders.ContainsKey(virtualScene.RegionInfo.originRegionID))
+                    m_forwarders.Remove(virtualScene.RegionInfo.originRegionID);
+
+                RegionCombinerModuleIndividualForwarder forwarder =
+                    new RegionCombinerModuleIndividualForwarder(m_rootScene, virtualScene);
+                m_forwarders.Add(virtualScene.RegionInfo.originRegionID, forwarder);
+
+                virtualScene.EventManager.OnNewClient += forwarder.ClientConnect;
+                virtualScene.EventManager.OnClientClosed += forwarder.ClientClosed;
+            }
+        }
+
+        public void RemoveSceneFromEventForwarding (Scene virtualScene)
+        {
+            lock (m_forwarders)
+            {
+                RegionCombinerModuleIndividualForwarder forwarder = m_forwarders[virtualScene.RegionInfo.originRegionID];
+                virtualScene.EventManager.OnNewClient -= forwarder.ClientConnect;
+                virtualScene.EventManager.OnClientClosed -= forwarder.ClientClosed;
+                m_forwarders.Remove(virtualScene.RegionInfo.originRegionID);
+            }
+            lock (m_virtScene)
+            {
+                if (m_virtScene.ContainsKey(virtualScene.RegionInfo.originRegionID))
+                {
+                    m_virtScene.Remove(virtualScene.RegionInfo.originRegionID);
+                }
+            }
+        }
+    }
+
+    public class RegionCombinerModuleIndividualForwarder
+    {
+        private Scene m_rootScene;
+        private Scene m_virtScene;
+        public RegionCombinerModuleIndividualForwarder(Scene rootScene, Scene virtScene)
+        {
+            m_rootScene = rootScene;
+            m_virtScene = virtScene;
+        }
+
+        public void ClientConnect(IClientAPI client)
+        {
+
+            m_virtScene.UnSubscribeToClientPrimEvents(client);
+            m_virtScene.UnSubscribeToClientPrimRezEvents(client);
+            m_virtScene.UnSubscribeToClientInventoryEvents(client);
+            m_virtScene.UnSubscribeToClientAttachmentEvents(client);
+            m_virtScene.UnSubscribeToClientTeleportEvents(client);
+            m_virtScene.UnSubscribeToClientScriptEvents(client);
+            m_virtScene.UnSubscribeToClientGodEvents(client);
+            m_virtScene.UnSubscribeToClientNetworkEvents(client);
+
+            m_rootScene.SubscribeToClientPrimEvents(client);
+            client.OnAddPrim += LocalAddNewPrim;
+            client.OnRezObject += LocalRezObject;
+            m_rootScene.SubscribeToClientInventoryEvents(client);
+            m_rootScene.SubscribeToClientAttachmentEvents(client);
+            m_rootScene.SubscribeToClientTeleportEvents(client);
+            m_rootScene.SubscribeToClientScriptEvents(client);
+            m_rootScene.SubscribeToClientGodEvents(client);
+            m_rootScene.SubscribeToClientNetworkEvents(client);
+        }
+        public void ClientClosed(UUID clientid, Scene scene)
+        {
+
+        }
+
+
+        private void LocalRezObject(IClientAPI remoteclient, UUID itemid, Vector3 rayend, Vector3 raystart, UUID raytargetid, byte bypassraycast, bool rayendisintersection, bool rezselected, bool removeitem, UUID fromtaskid)
+        {     
+            int differenceX = (int)m_virtScene.RegionInfo.RegionLocX - (int)m_rootScene.RegionInfo.RegionLocX;
+            int differenceY = (int)m_virtScene.RegionInfo.RegionLocY - (int)m_rootScene.RegionInfo.RegionLocY;
+            rayend.X += differenceX * (int)Constants.RegionSize;
+            rayend.Y += differenceY * (int)Constants.RegionSize;
+            raystart.X += differenceX * (int)Constants.RegionSize;
+            raystart.Y += differenceY * (int)Constants.RegionSize;
+
+            m_rootScene.RezObject(remoteclient, itemid, rayend, raystart, raytargetid, bypassraycast,
+                                  rayendisintersection, rezselected, removeitem, fromtaskid);
+
+        }
+
+        private void LocalAddNewPrim(UUID ownerid, UUID groupid, Vector3 rayend, Quaternion rot, PrimitiveBaseShape shape, byte bypassraycast, Vector3 raystart, UUID raytargetid, byte rayendisintersection)
+        {
+            int differenceX = (int)m_virtScene.RegionInfo.RegionLocX - (int)m_rootScene.RegionInfo.RegionLocX;
+            int differenceY = (int)m_virtScene.RegionInfo.RegionLocY - (int)m_rootScene.RegionInfo.RegionLocY;
+            rayend.X += differenceX * (int)Constants.RegionSize;
+            rayend.Y += differenceY * (int)Constants.RegionSize;
+            raystart.X += differenceX * (int)Constants.RegionSize;
+            raystart.Y += differenceY * (int)Constants.RegionSize;
+            m_rootScene.AddNewPrim(ownerid, groupid, rayend, rot, shape, bypassraycast, raystart, raytargetid,
+                                   rayendisintersection);
+
+        }
     }
 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 1d0da4c..c25ae10 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2365,14 +2365,40 @@ namespace OpenSim.Region.Framework.Scenes
             EventManager.TriggerOnNewClient(client);
         }
 
+        
+
         /// <summary>
         /// Register for events from the client
         /// </summary>
         /// <param name="client">The IClientAPI of the connected client</param>
-        protected virtual void SubscribeToClientEvents(IClientAPI client)
+        public virtual void SubscribeToClientEvents(IClientAPI client)
+        {
+            SubscribeToClientTerrainEvents(client);
+            SubscribeToClientPrimEvents(client);
+            SubscribeToClientPrimRezEvents(client);
+            SubscribeToClientInventoryEvents(client);
+            SubscribeToClientAttachmentEvents(client);
+            SubscribeToClientTeleportEvents(client);
+            SubscribeToClientScriptEvents(client);
+            SubscribeToClientParcelEvents(client);
+            SubscribeToClientGridEvents(client);
+            SubscribeToClientGodEvents(client);
+
+            SubscribeToClientNetworkEvents(client);
+            
+
+            // EventManager.TriggerOnNewClient(client);
+        }
+
+        public virtual void SubscribeToClientTerrainEvents(IClientAPI client)
         {
             client.OnRegionHandShakeReply += SendLayerData;
-            client.OnAddPrim += AddNewPrim;
+            client.OnUnackedTerrain += TerrainUnAcked;
+        }
+        
+        public virtual void SubscribeToClientPrimEvents(IClientAPI client)
+        {
+            
             client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimPosition;
             client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
             client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimRotation;
@@ -2384,8 +2410,6 @@ namespace OpenSim.Region.Framework.Scenes
             client.OnUpdateExtraParams += m_sceneGraph.UpdateExtraParam;
             client.OnUpdatePrimShape += m_sceneGraph.UpdatePrimShape;
             client.OnUpdatePrimTexture += m_sceneGraph.UpdatePrimTexture;
-            client.OnTeleportLocationRequest += RequestTeleportLocation;
-            client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
             client.OnObjectRequest += RequestPrim;
             client.OnObjectSelect += SelectPrim;
             client.OnObjectDeselect += DeselectPrim;
@@ -2393,15 +2417,7 @@ namespace OpenSim.Region.Framework.Scenes
             client.OnSpinStart += m_sceneGraph.SpinStart;
             client.OnSpinUpdate += m_sceneGraph.SpinObject;
             client.OnDeRezObject += DeRezObject;
-            client.OnRezObject += RezObject;
-            client.OnRezSingleAttachmentFromInv += RezSingleAttachment;
-            client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments;
-            client.OnDetachAttachmentIntoInv += DetachSingleAttachmentToInv;
-            client.OnObjectAttach += m_sceneGraph.AttachObject;
-            client.OnObjectDetach += m_sceneGraph.DetachObject;
-            client.OnObjectDrop += m_sceneGraph.DropObject;
-            client.OnNameFromUUIDRequest += CommsManager.HandleUUIDNameRequest;
-            client.OnObjectDescription += m_sceneGraph.PrimDescription;
+            
             client.OnObjectName += m_sceneGraph.PrimName;
             client.OnObjectClickAction += m_sceneGraph.PrimClickAction;
             client.OnObjectMaterial += m_sceneGraph.PrimMaterial;
@@ -2412,7 +2428,24 @@ namespace OpenSim.Region.Framework.Scenes
             client.OnUpdatePrimFlags += m_sceneGraph.UpdatePrimFlags;
             client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily;
             client.OnObjectPermissions += HandleObjectPermissionsUpdate;
+            client.OnGrabObject += ProcessObjectGrab;
+            client.OnDeGrabObject += ProcessObjectDeGrab;
+            client.OnUndo += m_sceneGraph.HandleUndo;
+            client.OnObjectDescription += m_sceneGraph.PrimDescription;
+            client.OnObjectDrop += m_sceneGraph.DropObject;
+            client.OnObjectSaleInfo += ObjectSaleInfo;
+            client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable;
+            client.OnObjectOwner += ObjectOwner;
+        }
+
+        public virtual void SubscribeToClientPrimRezEvents(IClientAPI client)
+        {
+            client.OnAddPrim += AddNewPrim;
+            client.OnRezObject += RezObject;
+        }
 
+        public virtual void SubscribeToClientInventoryEvents(IClientAPI client)
+        {
             client.OnCreateNewInventoryItem += CreateNewInventoryItem;
             client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder;
             client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder;
@@ -2430,36 +2463,217 @@ namespace OpenSim.Region.Framework.Scenes
             client.OnRemoveTaskItem += RemoveTaskInventory;
             client.OnUpdateTaskInventory += UpdateTaskInventory;
             client.OnMoveTaskItem += ClientMoveTaskInventoryItem;
+        }
 
-            client.OnGrabObject += ProcessObjectGrab;
-            client.OnDeGrabObject += ProcessObjectDeGrab;
-            client.OnMoneyTransferRequest += ProcessMoneyTransferRequest;
-            client.OnParcelBuy += ProcessParcelBuy;
-            client.OnAvatarPickerRequest += ProcessAvatarPickerRequest;
-            client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable;
+        public virtual void SubscribeToClientAttachmentEvents(IClientAPI client)
+        {
+            client.OnRezSingleAttachmentFromInv += RezSingleAttachment;
+            client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments;
+            client.OnDetachAttachmentIntoInv += DetachSingleAttachmentToInv;
+            client.OnObjectAttach += m_sceneGraph.AttachObject;
+            client.OnObjectDetach += m_sceneGraph.DetachObject;
+        }
+
+        public virtual void SubscribeToClientTeleportEvents(IClientAPI client)
+        {
+            client.OnTeleportLocationRequest += RequestTeleportLocation;
+            client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
             client.OnTeleportHomeRequest += TeleportClientHome;
-            client.OnSetStartLocationRequest += SetHomeRezPoint;
-            client.OnUndo += m_sceneGraph.HandleUndo;
-            client.OnObjectGroupRequest += m_sceneGraph.HandleObjectGroupUpdate;
-            client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel;
-            client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime;
-            client.OnObjectSaleInfo += ObjectSaleInfo;
+        }
+
+        public virtual void SubscribeToClientScriptEvents(IClientAPI client)
+        {
             client.OnScriptReset += ProcessScriptReset;
             client.OnGetScriptRunning += GetScriptRunning;
             client.OnSetScriptRunning += SetScriptRunning;
+        }
+
+        public virtual void SubscribeToClientParcelEvents(IClientAPI client)
+        {
+            client.OnObjectGroupRequest += m_sceneGraph.HandleObjectGroupUpdate;
+            client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel;
+            client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime;
+            client.OnParcelBuy += ProcessParcelBuy;
+        }
+
+        public virtual void SubscribeToClientGridEvents(IClientAPI client)
+        {
+            client.OnNameFromUUIDRequest += CommsManager.HandleUUIDNameRequest;
+            client.OnMoneyTransferRequest += ProcessMoneyTransferRequest;
+            client.OnAvatarPickerRequest += ProcessAvatarPickerRequest;
+            client.OnSetStartLocationRequest += SetHomeRezPoint;
             client.OnRegionHandleRequest += RegionHandleRequest;
-            client.OnUnackedTerrain += TerrainUnAcked;
-            client.OnObjectOwner += ObjectOwner;
+        }
 
+        public virtual void SubscribeToClientGodEvents(IClientAPI client)
+        {
             IGodsModule godsModule = RequestModuleInterface<IGodsModule>();
             client.OnGodKickUser += godsModule.KickUser;
             client.OnRequestGodlikePowers += godsModule.RequestGodlikePowers;
+        }
 
+        public virtual void SubscribeToClientNetworkEvents(IClientAPI client)
+        {
             client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats;
+        }
+
+        protected virtual void UnsubscribeToClientEvents(IClientAPI client)
+        {
+            
+        }
+
+        /// <summary>
+        /// Register for events from the client
+        /// </summary>
+        /// <param name="client">The IClientAPI of the connected client</param>
+        public virtual void UnSubscribeToClientEvents(IClientAPI client)
+        {
+            UnSubscribeToClientTerrainEvents(client);
+            UnSubscribeToClientPrimEvents(client);
+            UnSubscribeToClientPrimRezEvents(client);
+            UnSubscribeToClientInventoryEvents(client);
+            UnSubscribeToClientAttachmentEvents(client);
+            UnSubscribeToClientTeleportEvents(client);
+            UnSubscribeToClientScriptEvents(client);
+            UnSubscribeToClientParcelEvents(client);
+            UnSubscribeToClientGridEvents(client);
+            UnSubscribeToClientGodEvents(client);
+
+            UnSubscribeToClientNetworkEvents(client);
+
 
             // EventManager.TriggerOnNewClient(client);
         }
 
+        public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client)
+        {
+            client.OnRegionHandShakeReply -= SendLayerData;
+            client.OnUnackedTerrain -= TerrainUnAcked;
+        }
+
+        public virtual void UnSubscribeToClientPrimEvents(IClientAPI client)
+        {
+            client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimPosition;
+            client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
+            client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimRotation;
+            client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimRotation;
+            client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
+            client.OnUpdatePrimSingleRotationPosition -= m_sceneGraph.UpdatePrimSingleRotationPosition;
+            client.OnUpdatePrimScale -= m_sceneGraph.UpdatePrimScale;
+            client.OnUpdatePrimGroupScale -= m_sceneGraph.UpdatePrimGroupScale;
+            client.OnUpdateExtraParams -= m_sceneGraph.UpdateExtraParam;
+            client.OnUpdatePrimShape -= m_sceneGraph.UpdatePrimShape;
+            client.OnUpdatePrimTexture -= m_sceneGraph.UpdatePrimTexture;
+            client.OnObjectRequest -= RequestPrim;
+            client.OnObjectSelect -= SelectPrim;
+            client.OnObjectDeselect -= DeselectPrim;
+            client.OnGrabUpdate -= m_sceneGraph.MoveObject;
+            client.OnSpinStart -= m_sceneGraph.SpinStart;
+            client.OnSpinUpdate -= m_sceneGraph.SpinObject;
+            client.OnDeRezObject -= DeRezObject;
+            client.OnObjectName -= m_sceneGraph.PrimName;
+            client.OnObjectClickAction -= m_sceneGraph.PrimClickAction;
+            client.OnObjectMaterial -= m_sceneGraph.PrimMaterial;
+            client.OnLinkObjects -= m_sceneGraph.LinkObjects;
+            client.OnDelinkObjects -= m_sceneGraph.DelinkObjects;
+            client.OnObjectDuplicate -= m_sceneGraph.DuplicateObject;
+            client.OnObjectDuplicateOnRay -= doObjectDuplicateOnRay;
+            client.OnUpdatePrimFlags -= m_sceneGraph.UpdatePrimFlags;
+            client.OnRequestObjectPropertiesFamily -= m_sceneGraph.RequestObjectPropertiesFamily;
+            client.OnObjectPermissions -= HandleObjectPermissionsUpdate;
+            client.OnGrabObject -= ProcessObjectGrab;
+            client.OnDeGrabObject -= ProcessObjectDeGrab;
+            client.OnUndo -= m_sceneGraph.HandleUndo;
+            client.OnObjectDescription -= m_sceneGraph.PrimDescription;
+            client.OnObjectDrop -= m_sceneGraph.DropObject;
+            client.OnObjectSaleInfo -= ObjectSaleInfo;
+            client.OnObjectIncludeInSearch -= m_sceneGraph.MakeObjectSearchable;
+            client.OnObjectOwner -= ObjectOwner;
+        }
+
+        public virtual void UnSubscribeToClientPrimRezEvents(IClientAPI client)
+        {
+            client.OnAddPrim -= AddNewPrim;
+            client.OnRezObject -= RezObject;
+        }
+
+
+        public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client)
+        {
+            client.OnCreateNewInventoryItem -= CreateNewInventoryItem;
+            client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder;
+            client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder;
+            client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!!
+            client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents;
+            client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!!
+            client.OnFetchInventory -= HandleFetchInventory;
+            client.OnUpdateInventoryItem -= UpdateInventoryItemAsset;
+            client.OnCopyInventoryItem -= CopyInventoryItem;
+            client.OnMoveInventoryItem -= MoveInventoryItem;
+            client.OnRemoveInventoryItem -= RemoveInventoryItem;
+            client.OnRemoveInventoryFolder -= RemoveInventoryFolder;
+            client.OnRezScript -= RezScript;
+            client.OnRequestTaskInventory -= RequestTaskInventory;
+            client.OnRemoveTaskItem -= RemoveTaskInventory;
+            client.OnUpdateTaskInventory -= UpdateTaskInventory;
+            client.OnMoveTaskItem -= ClientMoveTaskInventoryItem;
+        }
+
+        public virtual void UnSubscribeToClientAttachmentEvents(IClientAPI client)
+        {
+            client.OnRezSingleAttachmentFromInv -= RezSingleAttachment;
+            client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachments;
+            client.OnDetachAttachmentIntoInv -= DetachSingleAttachmentToInv;
+            client.OnObjectAttach -= m_sceneGraph.AttachObject;
+            client.OnObjectDetach -= m_sceneGraph.DetachObject;
+        }
+
+        public virtual void UnSubscribeToClientTeleportEvents(IClientAPI client)
+        {
+            client.OnTeleportLocationRequest -= RequestTeleportLocation;
+            client.OnTeleportLandmarkRequest -= RequestTeleportLandmark;
+            client.OnTeleportHomeRequest -= TeleportClientHome;
+        }
+
+        public virtual void UnSubscribeToClientScriptEvents(IClientAPI client)
+        {
+            client.OnScriptReset -= ProcessScriptReset;
+            client.OnGetScriptRunning -= GetScriptRunning;
+            client.OnSetScriptRunning -= SetScriptRunning;
+        }
+
+        public virtual void UnSubscribeToClientParcelEvents(IClientAPI client)
+        {
+            client.OnObjectGroupRequest -= m_sceneGraph.HandleObjectGroupUpdate;
+            client.OnParcelReturnObjectsRequest -= LandChannel.ReturnObjectsInParcel;
+            client.OnParcelSetOtherCleanTime -= LandChannel.SetParcelOtherCleanTime;
+            client.OnParcelBuy -= ProcessParcelBuy;
+        }
+
+        public virtual void UnSubscribeToClientGridEvents(IClientAPI client)
+        {
+            client.OnNameFromUUIDRequest -= CommsManager.HandleUUIDNameRequest;
+            client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest;
+            client.OnAvatarPickerRequest -= ProcessAvatarPickerRequest;
+            client.OnSetStartLocationRequest -= SetHomeRezPoint;
+            client.OnRegionHandleRequest -= RegionHandleRequest;
+        }
+
+        public virtual void UnSubscribeToClientGodEvents(IClientAPI client)
+        {
+            IGodsModule godsModule = RequestModuleInterface<IGodsModule>();
+            client.OnGodKickUser -= godsModule.KickUser;
+            client.OnRequestGodlikePowers -= godsModule.RequestGodlikePowers;
+        }
+
+        public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client)
+        {
+            client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats;
+        }
+
+
+        
+
         /// <summary>
         /// Teleport an avatar to their home region
         /// </summary>
-- 
cgit v1.1