From 1959eb8372b6c8e35e1afa435504e9ef41dec958 Mon Sep 17 00:00:00 2001 From: Glenn Martin Date: Mon, 20 Apr 2015 14:55:00 -0400 Subject: Moved over metrics from previous OpenSim 0.8.0.3 repository (this new repository is now the master branch from OpenSim). --- .../Framework/Monitoring/SimExtraStatsCollector.cs | 47 +++++ OpenSim/Region/Framework/Scenes/Scene.cs | 108 ++++++++++- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 59 +++++- .../Region/Framework/Scenes/SimStatsReporter.cs | 216 +++++++++++++++++++-- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 36 ++++ bin/OpenSimDefaults.ini | 2 +- 6 files changed, 449 insertions(+), 19 deletions(-) mode change 100644 => 100755 OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/Scene.cs mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/SceneGraph.cs mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/SimStatsReporter.cs mode change 100644 => 100755 OpenSim/Region/ScriptEngine/XEngine/XEngine.cs mode change 100644 => 100755 bin/OpenSimDefaults.ini diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs old mode 100644 new mode 100755 index f6f458d..98fa65a --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using OpenMetaverse; @@ -71,6 +72,10 @@ namespace OpenSim.Framework.Monitoring private volatile float pendingUploads; private volatile float activeScripts; private volatile float scriptLinesPerSecond; + private volatile float m_usersLoggingIn; + private volatile float m_totalGeoPrims; + private volatile float m_totalMeshes; + private volatile float m_inUseThreads; // /// // /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the @@ -249,6 +254,10 @@ namespace OpenSim.Framework.Monitoring { // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original // SimStatsPacket that was being used). + + // For an unknown reason the original designers decided not to + // include the spare MS statistic inside of this class, this is + // located inside the StatsBlock at location 21 thus it is skipped timeDilation = stats.StatsBlock[0].StatValue; simFps = stats.StatsBlock[1].StatValue; physicsFps = stats.StatsBlock[2].StatValue; @@ -270,6 +279,10 @@ namespace OpenSim.Framework.Monitoring pendingUploads = stats.StatsBlock[18].StatValue; activeScripts = stats.StatsBlock[19].StatValue; scriptLinesPerSecond = stats.StatsBlock[20].StatValue; + m_usersLoggingIn = stats.StatsBlock[22].StatValue; + m_totalGeoPrims = stats.StatsBlock[23].StatValue; + m_totalMeshes = stats.StatsBlock[24].StatValue; + m_inUseThreads = stats.StatsBlock[25].StatValue; } /// @@ -407,6 +420,23 @@ Asset service request failures: {3}" + Environment.NewLine, /// public override OSDMap OReport(string uptime, string version) { + // Get the amount of physical memory, allocated with the instance of this program, in kilobytes; + // the working set is the set of memory pages currently visible to this program in physical RAM + // memory and includes both shared (e.g. system libraries) and private data + double memUsage = Process.GetCurrentProcess().WorkingSet64 / 1024.0; + + // Get the number of threads from the system that are currently + // running + int numberThreadsRunning = 0; + foreach (ProcessThread currentThread in + Process.GetCurrentProcess().Threads) + { + if (currentThread.ThreadState == ThreadState.Running) + { + numberThreadsRunning++; + } + } + OSDMap args = new OSDMap(30); // args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); // args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", @@ -443,6 +473,23 @@ Asset service request failures: {3}" + Environment.NewLine, args["Memory"] = OSD.FromString (base.XReport (uptime, version)); args["Uptime"] = OSD.FromString (uptime); args["Version"] = OSD.FromString (version); + + args["Logging in Users"] = OSD.FromString(String.Format("{0:0.##}", + m_usersLoggingIn)); + args["GeoPrims"] = OSD.FromString(String.Format("{0:0.##}", + m_totalGeoPrims)); + args["Mesh Objects"] = OSD.FromString(String.Format("{0:0.##}", + m_totalMeshes)); + args["Polygon Count"] = OSD.FromString(String.Format("{0:0.##}", 0)); + args["Texture Count"] = OSD.FromString(String.Format("{0:0.##}", 0)); + args["XEngine Thread Count"] = OSD.FromString(String.Format("{0:0.##}", + m_inUseThreads)); + args["Util Thread Count"] = OSD.FromString(String.Format("{0:0.##}", + Util.GetSmartThreadPoolInfo().InUseThreads)); + args["System Thread Count"] = OSD.FromString(String.Format( + "{0:0.##}", numberThreadsRunning)); + args["ProcMem"] = OSD.FromString(String.Format("{0:#,###,###.##}", + memUsage)); return args; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs old mode 100644 new mode 100755 index 4715558..052567f --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -526,6 +526,13 @@ namespace OpenSim.Region.Framework.Scenes get { return m_sceneGraph.PhysicsScene.TimeDilation; } } + public void setThreadCount(int inUseThreads) + { + // Just pass the thread count information on its way as the Scene + // does not require the value for anything at this time + StatsReporter.SetThreadCount(inUseThreads); + } + public SceneCommunicationService SceneGridService { get { return m_sceneGridService; } @@ -1107,7 +1114,35 @@ namespace OpenSim.Region.Framework.Scenes #endregion Interest Management - StatsReporter = new SimStatsReporter(this); + // The timer used by the Stopwatch class depends on the system hardware and operating system; inform + // if the timer is based on a high-resolution performance counter or based on the system timer; + // the performance counter will provide a more precise time than the system timer + if (Stopwatch.IsHighResolution) + m_log.InfoFormat("[SCENE]: Using high-resolution performance counter for statistics."); + else + m_log.InfoFormat("[SCENE]: Using system timer for statistics."); + + // Acquire the statistics section of the OpenSim.ini file located + // in the bin directory + IConfig statisticsConfig = m_config.Configs["Statistics"]; + + // Confirm that the statistics section existed in the configuration + // file + if (statisticsConfig != null) + { + // Create the StatsReporter using the number of frames to store + // for the frame time statistics, or 10 frames if the config + // file doesn't contain a value + StatsReporter = new SimStatsReporter(this, + statisticsConfig.GetInt("NumberOfFrames", 10)); + } + else + { + // Create a StatsReporter with the current scene and a default + // 10 frames stored for the frame time statistics + StatsReporter = new SimStatsReporter(this); + } + StatsReporter.OnSendStatsResult += SendSimStatsPackets; StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; @@ -1607,6 +1642,21 @@ namespace OpenSim.Region.Framework.Scenes float physicsFPS = 0f; int previousFrameTick, tmpMS; + // These variables will be used to save the precise frame time using the + // Stopwatch class of Microsoft SDK; the times are recorded at the start + // and end of a parcticular section of code, and then used to calculate + // the frame times, which are the sums of the sections for each given name + double preciseTotalFrameTime = 0.0; + double preciseSimFrameTime = 0.0; + double precisePhysicsFrameTime = 0.0; + Stopwatch totalFrameStopwatch = new Stopwatch(); + Stopwatch simFrameStopwatch = new Stopwatch(); + Stopwatch physicsFrameStopwatch = new Stopwatch(); + + // Begin the stopwatch to keep track of the time that the frame + // started running to determine how long the frame took to complete + totalFrameStopwatch.Start(); + while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) { ++Frame; @@ -1627,20 +1677,47 @@ namespace OpenSim.Region.Framework.Scenes terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); } + // At several points inside the code there was a need to + // create a more precise measurement of time elapsed. This + // led to the addition of variables that have a similar + // function and thus remain tightly connected to their + // original counterparts. However, the original code is + // not receiving comments from our group because we don't + // feel right modifying the code to that degree at this + // point in time, the precise values all begin with the + // keyword precise + tmpMS = Util.EnvironmentTickCount(); + + // Begin the stopwatch to track the time to prepare physics + physicsFrameStopwatch.Start(); if (PhysicsEnabled && Frame % m_update_physics == 0) m_sceneGraph.UpdatePreparePhysics(); + + // Get the time it took to prepare the physics, this + // would report the most precise time that physics was + // running on the machine and should the physics not be + // enabled will report the time it took to check if physics + // was enabled + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds; physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); // Apply any pending avatar force input to the avatar's velocity tmpMS = Util.EnvironmentTickCount(); + simFrameStopwatch.Start(); if (Frame % m_update_entitymovement == 0) m_sceneGraph.UpdateScenePresenceMovement(); + + // Get the simulation frame time that the avatar force input took + simFrameStopwatch.Stop(); + preciseSimFrameTime = simFrameStopwatch.Elapsed.TotalMilliseconds; agentMS = Util.EnvironmentTickCountSubtract(tmpMS); // Perform the main physics update. This will do the actual work of moving objects and avatars according to their // velocity tmpMS = Util.EnvironmentTickCount(); + physicsFrameStopwatch.Restart(); if (Frame % m_update_physics == 0) { if (PhysicsEnabled) @@ -1649,8 +1726,14 @@ namespace OpenSim.Region.Framework.Scenes if (SynchronizeScene != null) SynchronizeScene(this); } + + // Add the main physics update time to the prepare physics time + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); + // Start the stopwatch for the remainder of the simulation + simFrameStopwatch.Restart(); tmpMS = Util.EnvironmentTickCount(); // Check if any objects have reached their targets @@ -1754,6 +1837,10 @@ namespace OpenSim.Region.Framework.Scenes spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); } + // Get the elapsed time for the simulation frame + simFrameStopwatch.Stop(); + preciseSimFrameTime += simFrameStopwatch.Elapsed.TotalMilliseconds; + previousFrameTick = m_lastFrameTick; frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); m_lastFrameTick = Util.EnvironmentTickCount(); @@ -1771,6 +1858,15 @@ namespace OpenSim.Region.Framework.Scenes StatsReporter.AddSpareMS(spareMS); StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); + // Send the correct time values to the stats reporter for the + // frame times + StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime, + preciseSimFrameTime, precisePhysicsFrameTime, 0.0); + + // Send the correct number of frames that the physics library + // has processed to the stats reporter + StatsReporter.addPhysicsFrame(1); + // Optionally warn if a frame takes double the amount of time that it should. if (DebugUpdates && Util.EnvironmentTickCountSubtract( @@ -1782,6 +1878,9 @@ namespace OpenSim.Region.Framework.Scenes RegionInfo.RegionName); } + // Finished updating scene frame, so stop the total frame's Stopwatch + totalFrameStopwatch.Stop(); + return spareMS >= 0; } @@ -2702,6 +2801,9 @@ namespace OpenSim.Region.Framework.Scenes bool vialogin; bool reallyNew = true; + // Update the number of users attempting to login + StatsReporter.UpdateUsersLoggingIn(true); + // Validation occurs in LLUDPServer // // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with @@ -2786,6 +2888,10 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerOnClientLogin(client); } + // User has logged into the scene so update the list of users logging + // in + StatsReporter.UpdateUsersLoggingIn(false); + m_LastLogin = Util.EnvironmentTickCount(); return sp; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs old mode 100644 new mode 100755 index 51f50d9..c2e9b61 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -67,7 +67,9 @@ namespace OpenSim.Region.Framework.Scenes protected Scene m_parentScene; protected Dictionary m_updateList = new Dictionary(); protected int m_numRootAgents = 0; + protected int m_numTotalPrim = 0; protected int m_numPrim = 0; + protected int m_numMesh = 0; protected int m_numChildAgents = 0; protected int m_physicalPrim = 0; @@ -368,7 +370,8 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = sceneObject.Parts; - // Clamp child prim sizes and add child prims to the m_numPrim count + // Clamp the sizes (scales) of the child prims and add the child prims to the count of all primitives + // (meshes and geometric primitives) in the scene; add child prims to m_numTotalPrim count if (m_parentScene.m_clampPrimSize) { foreach (SceneObjectPart part in parts) @@ -382,7 +385,19 @@ namespace OpenSim.Region.Framework.Scenes part.Shape.Scale = scale; } } - m_numPrim += parts.Length; + m_numTotalPrim += parts.Length; + + // Go through all parts (geometric primitives and meshes) of this Scene Object + foreach (SceneObjectPart part in parts) + { + // Keep track of the total number of meshes or geometric primitives now in the scene; + // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to + // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives + if (part.GetPrimType() == PrimType.SCULPT) + m_numMesh++; + else + m_numPrim++; + } sceneObject.AttachToScene(m_parentScene); @@ -437,7 +452,21 @@ namespace OpenSim.Region.Framework.Scenes if (!resultOfObjectLinked) { - m_numPrim -= grp.PrimCount; + // Decrement the total number of primitives (meshes and geometric primitives) + // that are part of the Scene Object being removed + m_numTotalPrim -= grp.PrimCount; + + // Go through all parts (primitives and meshes) of this Scene Object + foreach (SceneObjectPart part in grp.Parts) + { + // Keep track of the total number of meshes or geometric primitives left in the scene; + // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to + // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives + if (part.GetPrimType() == PrimType.SCULPT) + m_numMesh--; + else + m_numPrim--; + } if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) RemovePhysicalPrim(grp.PrimCount); @@ -687,9 +716,19 @@ namespace OpenSim.Region.Framework.Scenes public int GetTotalObjectsCount() { + return m_numTotalPrim; + } + + public int GetTotalPrimObjectsCount() + { return m_numPrim; } + public int GetTotalMeshObjectsCount() + { + return m_numMesh; + } + public int GetActiveObjectsCount() { return m_physicalPrim; @@ -1970,7 +2009,19 @@ namespace OpenSim.Region.Framework.Scenes // think it's selected, so it will never send a deselect... copy.IsSelected = false; - m_numPrim += copy.Parts.Length; + m_numTotalPrim += copy.Parts.Length; + + // Go through all parts (primitives and meshes) of this Scene Object + foreach (SceneObjectPart part in copy.Parts) + { + // Keep track of the total number of meshes or geometric primitives now in the scene; + // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to + // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives + if (part.GetPrimType() == PrimType.SCULPT) + m_numMesh++; + else + m_numPrim++; + } if (rot != Quaternion.Identity) { diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs old mode 100644 new mode 100755 index 8f1e345..b6da636 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -61,6 +61,10 @@ namespace OpenSim.Region.Framework.Scenes private YourStatsAreWrong handlerStatsIncorrect; + // Determines the size of the array that is used to collect StatBlocks + // for sending to the SimStats and SimExtraStatsCollector + private const int m_statisticArraySize = 26; + /// /// These are the IDs of stats sent in the StatsPacket to the viewer. /// @@ -104,7 +108,11 @@ namespace OpenSim.Region.Framework.Scenes ScriptEps = 31, SimSpareMs = 32, SimSleepMs = 33, - SimIoPumpTime = 34 + SimIoPumpTime = 34, + UsersLoggingIn = 35, + TotalGeoPrim = 36, + TotalMesh = 37, + ThreadCount = 38 } /// @@ -175,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes // saved last reported value so there is something available for llGetRegionFPS private float lastReportedSimFPS; - private float[] lastReportedSimStats = new float[22]; + private float[] lastReportedSimStats = new float[m_statisticArraySize]; private float m_pfps; /// @@ -202,6 +210,8 @@ namespace OpenSim.Region.Framework.Scenes private int m_rootAgents; private int m_childAgents; private int m_numPrim; + private int m_numGeoPrim; + private int m_numMesh; private int m_inPacketsPerSecond; private int m_outPacketsPerSecond; private int m_activePrim; @@ -213,6 +223,34 @@ namespace OpenSim.Region.Framework.Scenes private int m_objectCapacity = 45000; + // This is the number of frames that will be stored and then averaged for + // the Total, Simulation, Physics, and Network Frame Time; It is set to + // 10 by default but can be changed by the OpenSim.ini configuration file + // NumberOfFrames parameter + private int m_numberFramesStored = 10; + + // The arrays that will hold the time it took to run the past N frames, + // where N is the num_frames_to_average given by the configuration file + private double[] m_totalFrameTimeMilliseconds; + private double[] m_simulationFrameTimeMilliseconds; + private double[] m_physicsFrameTimeMilliseconds; + private double[] m_networkFrameTimeMilliseconds; + + // The location of the next time in milliseconds that will be + // (over)written when the next frame completes + private int m_nextLocation = 0; + + // The correct number of frames that have completed since the last stats + // update for physics + private int m_numberPhysicsFrames; + + // The current number of users attempting to login to the region + private int m_usersLoggingIn; + + // The last reported value of threads from the SmartThreadPool inside of + // XEngine + private int m_inUseThreads; + private Scene m_scene; private RegionInfo ReportingRegion; @@ -223,6 +261,15 @@ namespace OpenSim.Region.Framework.Scenes public SimStatsReporter(Scene scene) { + // Initialize the different frame time arrays to the correct sizes + m_totalFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_simulationFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_physicsFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_networkFrameTimeMilliseconds = new double[m_numberFramesStored]; + + // Initialize the current number of users logging into the region + m_usersLoggingIn = 0; + m_scene = scene; m_reportedFpsCorrectionFactor = scene.MinFrameSeconds * m_nominalReportedFps; m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000); @@ -256,6 +303,14 @@ namespace OpenSim.Region.Framework.Scenes StatsManager.RegisterStat(SlowFramesStat); } + + public SimStatsReporter(Scene scene, int numberOfFrames) : this (scene) + { + // Store the number of frames from the OpenSim.ini configuration file + m_numberFramesStored = numberOfFrames; + } + + public void Close() { m_report.Elapsed -= TriggerStatsHeartbeat; @@ -289,10 +344,21 @@ namespace OpenSim.Region.Framework.Scenes private void statsHeartBeat(object sender, EventArgs e) { + double totalSumFrameTime; + double simulationSumFrameTime; + double physicsSumFrameTime; + double networkSumFrameTime; + float timeDilation; + int currentFrame; + if (!m_scene.Active) return; - SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[22]; + // Create arrays to hold the statistics for this current scene, + // these will be passed to the SimExtraStatsCollector, they are also + // sent to the SimStats class + SimStatsPacket.StatBlock[] sb = new + SimStatsPacket.StatBlock[m_statisticArraySize]; SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); // Know what's not thread safe in Mono... modifying timers. @@ -314,14 +380,21 @@ namespace OpenSim.Region.Framework.Scenes #region various statistic googly moogly + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window, this will be done as a + // new section given the title of our current project // We're going to lie about the FPS because we've been lying since 2008. The actual FPS is currently // locked at a maximum of 11. Maybe at some point this can change so that we're not lying. - int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); + //int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); + int reportedFPS = m_fps; // save the reported value so there is something available for llGetRegionFPS lastReportedSimFPS = reportedFPS / m_statsUpdateFactor; - float physfps = ((m_pfps / 1000)); + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window + //float physfps = ((m_pfps / 1000)); + float physfps = m_numberPhysicsFrames; //if (physfps > 600) //physfps = physfps - (physfps - 600); @@ -334,6 +407,8 @@ namespace OpenSim.Region.Framework.Scenes m_rootAgents = m_scene.SceneGraph.GetRootAgentCount(); m_childAgents = m_scene.SceneGraph.GetChildAgentCount(); m_numPrim = m_scene.SceneGraph.GetTotalObjectsCount(); + m_numGeoPrim = m_scene.SceneGraph.GetTotalPrimObjectsCount(); + m_numMesh = m_scene.SceneGraph.GetTotalMeshObjectsCount(); m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount(); m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount(); @@ -359,13 +434,48 @@ namespace OpenSim.Region.Framework.Scenes if (framesUpdated == 0) framesUpdated = 1; - for (int i = 0; i < 22; i++) + for (int i = 0; i < m_statisticArraySize; i++) { sb[i] = new SimStatsPacket.StatBlock(); } - + + // Resetting the sums of the frame times to prevent any errors + // in calculating the moving average for frame time + totalSumFrameTime = 0; + simulationSumFrameTime = 0; + physicsSumFrameTime = 0; + networkSumFrameTime = 0; + + // Loop through all the frames that were stored for the current + // heartbeat to process the moving average of frame times + for (int i = 0; i < m_numberFramesStored; i++) + { + // Sum up each frame time in order to calculate the moving + // average of frame time + totalSumFrameTime += m_totalFrameTimeMilliseconds[i]; + simulationSumFrameTime += + m_simulationFrameTimeMilliseconds[i]; + physicsSumFrameTime += m_physicsFrameTimeMilliseconds[i]; + networkSumFrameTime += m_networkFrameTimeMilliseconds[i]; + } + + // Get the index that represents the current frame based on the next one known; go back + // to the last index if next one is stated to restart at 0 + if (m_nextLocation == 0) + currentFrame = m_numberFramesStored - 1; + else + currentFrame = m_nextLocation - 1; + + // Calculate the time dilation; which is currently based on the ratio between the sum of the + // physics and simulation rate, and the set minimum time to run the scene's update; minFrameTime + // is given in seconds so multiply by 1000 to convert it to milliseconds + timeDilation = (float)(m_simulationFrameTimeMilliseconds[currentFrame] + + m_physicsFrameTimeMilliseconds[currentFrame]) / (m_scene.MinFrameTime * 1000); + + // ORIGINAL code commented out until we have time to add our own sb[0].StatID = (uint) Stats.TimeDilation; - sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); + //sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); + sb[0].StatValue = timeDilation; sb[1].StatID = (uint) Stats.SimFPS; sb[1].StatValue = reportedFPS / m_statsUpdateFactor; @@ -388,20 +498,27 @@ namespace OpenSim.Region.Framework.Scenes sb[7].StatID = (uint) Stats.ActivePrim; sb[7].StatValue = m_activePrim; + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window sb[8].StatID = (uint)Stats.FrameMS; - sb[8].StatValue = m_frameMS / framesUpdated; + //sb[8].StatValue = m_frameMS / framesUpdated; + sb[8].StatValue = (float) totalSumFrameTime / m_numberFramesStored; sb[9].StatID = (uint)Stats.NetMS; - sb[9].StatValue = m_netMS / framesUpdated; + //sb[9].StatValue = m_netMS / framesUpdated; + sb[9].StatValue = (float) networkSumFrameTime / m_numberFramesStored; sb[10].StatID = (uint)Stats.PhysicsMS; - sb[10].StatValue = m_physicsMS / framesUpdated; + //sb[10].StatValue = m_physicsMS / framesUpdated; + sb[10].StatValue = (float) physicsSumFrameTime / m_numberFramesStored; sb[11].StatID = (uint)Stats.ImageMS ; sb[11].StatValue = m_imageMS / framesUpdated; sb[12].StatID = (uint)Stats.OtherMS; - sb[12].StatValue = m_otherMS / framesUpdated; + //sb[12].StatValue = m_otherMS / framesUpdated; + sb[12].StatValue = (float) simulationSumFrameTime / + m_numberFramesStored; sb[13].StatID = (uint)Stats.InPacketsPerSecond; sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor); @@ -430,7 +547,25 @@ namespace OpenSim.Region.Framework.Scenes sb[21].StatID = (uint)Stats.SimSpareMs; sb[21].StatValue = m_spareMS / framesUpdated; - for (int i = 0; i < 22; i++) + // Added to track the number of users currently attempting to + // login to the region + sb[22].StatID = (uint)Stats.UsersLoggingIn; + sb[22].StatValue = m_usersLoggingIn; + + // Total number of geometric primitives in the scene + sb[23].StatID = (uint)Stats.TotalGeoPrim; + sb[23].StatValue = m_numGeoPrim; + + // Total number of mesh objects in the scene + sb[24].StatID = (uint)Stats.TotalMesh; + sb[24].StatValue = m_numMesh; + + // Added to track the current number of threads that XEngine is + // using + sb[25].StatID = (uint)Stats.ThreadCount; + sb[25].StatValue = m_inUseThreads; + + for (int i = 0; i < m_statisticArraySize; i++) { lastReportedSimStats[i] = sb[i].StatValue; } @@ -475,6 +610,10 @@ namespace OpenSim.Region.Framework.Scenes private void ResetValues() { + // Reset the number of frames that the physics library has + // processed since the last stats report + m_numberPhysicsFrames = 0; + m_timeDilation = 0; m_fps = 0; m_pfps = 0; @@ -605,6 +744,32 @@ namespace OpenSim.Region.Framework.Scenes m_otherMS += ms; } + public void addPhysicsFrame(int frames) + { + // Add the number of physics frames to the correct total physics + // frames + m_numberPhysicsFrames += frames; + } + + public void addFrameTimeMilliseconds(double total, double simulation, + double physics, double network) + { + // Save the frame times from the current frame into the appropriate + // arrays + m_totalFrameTimeMilliseconds[m_nextLocation] = total; + m_simulationFrameTimeMilliseconds[m_nextLocation] = simulation; + m_physicsFrameTimeMilliseconds[m_nextLocation] = physics; + m_networkFrameTimeMilliseconds[m_nextLocation] = network; + + // Update to the next location in the list + m_nextLocation++; + + // Since the list will begin to overwrite the oldest frame values + // first, the next location needs to loop back to the beginning of the + // list whenever it reaches the end + m_nextLocation = m_nextLocation % m_numberFramesStored; + } + public void AddPendingDownloads(int count) { m_pendingDownloads += count; @@ -627,6 +792,31 @@ namespace OpenSim.Region.Framework.Scenes AddunAckedBytes(unAckedBytes); } + public void UpdateUsersLoggingIn(bool isLoggingIn) + { + // Determine whether the user has started logging in or has completed + // logging into the region + if (isLoggingIn) + { + // The user is starting to login to the region so increment the + // number of users attempting to login to the region + m_usersLoggingIn++; + } + else + { + // The user has finished logging into the region so decrement the + // number of users logging into the region + m_usersLoggingIn--; + } + } + + public void SetThreadCount(int inUseThreads) + { + // Save the new number of threads to our member variable to send to + // the extra stats collector + m_inUseThreads = inUseThreads; + } + #endregion public Dictionary GetExtraSimStats() diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs old mode 100644 new mode 100755 index 54620d1..4e383f8 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1872,6 +1872,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine IScriptInstance instance = GetInstance(itemID); if (instance != null) instance.ApiResetScript(); + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public void ResetScript(UUID itemID) @@ -1879,6 +1885,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine IScriptInstance instance = GetInstance(itemID); if (instance != null) instance.ResetScript(m_WaitForEventCompletionOnScriptStop); + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public void StartScript(UUID itemID) @@ -1888,6 +1900,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.Start(); else m_runFlags.AddOrUpdate(itemID, true, 240); + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public void StopScript(UUID itemID) @@ -1903,6 +1921,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine // m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name); m_runFlags.AddOrUpdate(itemID, false, 240); } + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public DetectParams GetDetectParams(UUID itemID, int idx) @@ -2393,6 +2417,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.Suspend(); // else // m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public void ResumeScript(UUID itemID) @@ -2404,6 +2434,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.Resume(); // else // m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public bool HasScript(UUID itemID, out bool running) diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini old mode 100644 new mode 100755 index af37ccc..3422996 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -296,7 +296,7 @@ ; Simulator Stats URI ; Enable JSON simulator data by setting a URI name (case sensitive) ; Returns regular sim stats (SimFPS, ...) - ; Stats_URI = "jsonSimStats" + Stats_URI = "jsonSimStats" ; Simulator StatsManager URI ; Enable fetch of StatsManager registered stats. Fetch is query which can optionally -- cgit v1.1 From c3138f9f38420ae370078df3b0990a953f43b087 Mon Sep 17 00:00:00 2001 From: Robert Louden Date: Tue, 21 Apr 2015 16:15:48 -0400 Subject: Phase 2 additons with Frame Dilation metric. --- .../Framework/Monitoring/SimExtraStatsCollector.cs | 19 +- OpenSim/Region/Framework/Scenes/Scene.cs | 11370 ++++++++++--------- .../Region/Framework/Scenes/SimStatsReporter.cs | 52 +- 3 files changed, 5733 insertions(+), 5708 deletions(-) diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index 98fa65a..432efdb 100755 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs @@ -72,6 +72,7 @@ namespace OpenSim.Framework.Monitoring private volatile float pendingUploads; private volatile float activeScripts; private volatile float scriptLinesPerSecond; + private volatile float m_frameDilation; private volatile float m_usersLoggingIn; private volatile float m_totalGeoPrims; private volatile float m_totalMeshes; @@ -257,7 +258,7 @@ namespace OpenSim.Framework.Monitoring // For an unknown reason the original designers decided not to // include the spare MS statistic inside of this class, this is - // located inside the StatsBlock at location 21 thus it is skipped + // located inside the StatsBlock at location 21, thus it is skipped timeDilation = stats.StatsBlock[0].StatValue; simFps = stats.StatsBlock[1].StatValue; physicsFps = stats.StatsBlock[2].StatValue; @@ -279,10 +280,11 @@ namespace OpenSim.Framework.Monitoring pendingUploads = stats.StatsBlock[18].StatValue; activeScripts = stats.StatsBlock[19].StatValue; scriptLinesPerSecond = stats.StatsBlock[20].StatValue; - m_usersLoggingIn = stats.StatsBlock[22].StatValue; - m_totalGeoPrims = stats.StatsBlock[23].StatValue; - m_totalMeshes = stats.StatsBlock[24].StatValue; - m_inUseThreads = stats.StatsBlock[25].StatValue; + m_frameDilation = stats.StatsBlock[22].StatValue; + m_usersLoggingIn = stats.StatsBlock[23].StatValue; + m_totalGeoPrims = stats.StatsBlock[24].StatValue; + m_totalMeshes = stats.StatsBlock[25].StatValue; + m_inUseThreads = stats.StatsBlock[26].StatValue; } /// @@ -474,14 +476,13 @@ Asset service request failures: {3}" + Environment.NewLine, args["Uptime"] = OSD.FromString (uptime); args["Version"] = OSD.FromString (version); + args["FrameDilatn"] = OSD.FromString(String.Format("{0:0.##}", m_frameDilation)); args["Logging in Users"] = OSD.FromString(String.Format("{0:0.##}", - m_usersLoggingIn)); + m_usersLoggingIn)); args["GeoPrims"] = OSD.FromString(String.Format("{0:0.##}", m_totalGeoPrims)); args["Mesh Objects"] = OSD.FromString(String.Format("{0:0.##}", m_totalMeshes)); - args["Polygon Count"] = OSD.FromString(String.Format("{0:0.##}", 0)); - args["Texture Count"] = OSD.FromString(String.Format("{0:0.##}", 0)); args["XEngine Thread Count"] = OSD.FromString(String.Format("{0:0.##}", m_inUseThreads)); args["Util Thread Count"] = OSD.FromString(String.Format("{0:0.##}", @@ -489,7 +490,7 @@ Asset service request failures: {3}" + Environment.NewLine, args["System Thread Count"] = OSD.FromString(String.Format( "{0:0.##}", numberThreadsRunning)); args["ProcMem"] = OSD.FromString(String.Format("{0:#,###,###.##}", - memUsage)); + memUsage)); return args; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 052567f..31e4ee0 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -48,5960 +48,5982 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes.Scripting; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Region.Physics.Manager; -using Timer=System.Timers.Timer; +using Timer = System.Timers.Timer; using TPFlags = OpenSim.Framework.Constants.TeleportFlags; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using PermissionMask = OpenSim.Framework.PermissionMask; namespace OpenSim.Region.Framework.Scenes { - public delegate bool FilterAvatarList(ScenePresence avatar); - - public partial class Scene : SceneBase - { - private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; - private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; - - public delegate void SynchronizeSceneHandler(Scene scene); - - #region Fields - - public bool EmergencyMonitoring = false; - - /// - /// Show debug information about animations. - /// - public bool DebugAnimations { get; set; } - - /// - /// Show debug information about teleports. - /// - public bool DebugTeleporting { get; set; } - - /// - /// Show debug information about the scene loop. - /// - public bool DebugUpdates { get; set; } - - /// - /// If true then the scene is saved to persistent storage periodically, every m_update_backup frames and - /// if objects meet required conditions (m_dontPersistBefore and m_dontPersistAfter). - /// - /// - /// Even if false, the scene will still be saved on clean shutdown. - /// FIXME: Currently, setting this to false will mean that objects are not periodically returned from parcels. - /// This needs to be fixed. - /// - public bool PeriodicBackup { get; set; } - - /// - /// If false then the scene is never saved to persistence storage even if PeriodicBackup == true and even - /// if the scene is being shut down for the final time. - /// - public bool UseBackup { get; set; } - - /// - /// If false then physical objects are disabled, though collisions will continue as normal. - /// - public bool PhysicsEnabled - { - get - { - return m_physicsEnabled; - } - - set - { - m_physicsEnabled = value; - - if (PhysicsScene != null) - { - IPhysicsParameters physScene = PhysicsScene as IPhysicsParameters; - - if (physScene != null) - physScene.SetPhysicsParameter( - "Active", m_physicsEnabled.ToString(), PhysParameterEntry.APPLY_TO_NONE); - } - } - } - - private bool m_physicsEnabled; - - /// - /// If false then scripts are not enabled on the smiulator - /// - public bool ScriptsEnabled - { - get { return m_scripts_enabled; } - set - { - if (m_scripts_enabled != value) - { - if (!value) - { - m_log.Info("Stopping all Scripts in Scene"); - - EntityBase[] entities = Entities.GetEntities(); - foreach (EntityBase ent in entities) - { - if (ent is SceneObjectGroup) - ((SceneObjectGroup)ent).RemoveScriptInstances(false); - } - } - else - { - m_log.Info("Starting all Scripts in Scene"); - - EntityBase[] entities = Entities.GetEntities(); - foreach (EntityBase ent in entities) - { - if (ent is SceneObjectGroup) - { - SceneObjectGroup sog = (SceneObjectGroup)ent; - sog.CreateScriptInstances(0, false, DefaultScriptEngine, 0); - sog.ResumeScripts(); - } - } - } - - m_scripts_enabled = value; - } - } - } - private bool m_scripts_enabled; - - public SynchronizeSceneHandler SynchronizeScene; - - /// - /// Used to prevent simultaneous calls to code that adds and removes agents. - /// - private object m_removeClientLock = new object(); - - /// - /// Statistical information for this scene. - /// - public SimStatsReporter StatsReporter { get; private set; } - - /// - /// Controls whether physics can be applied to prims. Even if false, prims still have entries in a - /// PhysicsScene in order to perform collision detection - /// - public bool PhysicalPrims { get; private set; } - - /// - /// Controls whether prims can be collided with. - /// - /// - /// If this is set to false then prims cannot be subject to physics either. - /// - public bool CollidablePrims { get; private set; } - - /// - /// Minimum value of the size of a non-physical prim in each axis - /// - public float m_minNonphys = 0.001f; - - /// - /// Maximum value of the size of a non-physical prim in each axis - /// - public float m_maxNonphys = 256; - - /// - /// Minimum value of the size of a physical prim in each axis - /// - public float m_minPhys = 0.01f; - - /// - /// Maximum value of the size of a physical prim in each axis - /// - public float m_maxPhys = 64; - - /// - /// Max prims an object will hold - /// - public int m_linksetCapacity = 0; - - public bool m_clampPrimSize; - public bool m_trustBinaries; - public bool m_allowScriptCrossings = true; - - /// - /// Can avatars cross from and to this region? - /// - public bool AllowAvatarCrossing { get; set; } - - public bool m_useFlySlow; - public bool m_useTrashOnDelete = true; - - /// - /// Temporarily setting to trigger appearance resends at 60 second intervals. - /// - public bool SendPeriodicAppearanceUpdates { get; set; } - - /// - /// How much a root agent has to change position before updates are sent to viewers. - /// - public float RootPositionUpdateTolerance { get; set; } - - /// - /// How much a root agent has to rotate before updates are sent to viewers. - /// - public float RootRotationUpdateTolerance { get; set; } - - /// - /// How much a root agent has to change velocity before updates are sent to viewers. - /// - public float RootVelocityUpdateTolerance { get; set; } - - /// - /// If greater than 1, we only send terse updates to other root agents on every n updates. - /// - public int RootTerseUpdatePeriod { get; set; } - - /// - /// If greater than 1, we only send terse updates to child agents on every n updates. - /// - public int ChildTerseUpdatePeriod { get; set; } - - protected float m_defaultDrawDistance = 255.0f; - public float DefaultDrawDistance - { - // get { return m_defaultDrawDistance; } - get { - if (RegionInfo != null) - { - float largestDimension = Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); - m_defaultDrawDistance = Math.Max(m_defaultDrawDistance, largestDimension); - - } - return m_defaultDrawDistance; - } - } - - private List m_AllowedViewers = new List(); - private List m_BannedViewers = new List(); - - // TODO: need to figure out how allow client agents but deny - // root agents when ACL denies access to root agent - public bool m_strictAccessControl = true; - - public int MaxUndoCount { get; set; } - - public bool SeeIntoRegion { get; set; } - - // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; - public bool LoginLock = false; - - public bool StartDisabled = false; - public bool LoadingPrims; - public IXfer XferManager; - - // the minimum time that must elapse before a changed object will be considered for persisted - public long m_dontPersistBefore = DEFAULT_MIN_TIME_FOR_PERSISTENCE * 10000000L; - // the maximum time that must elapse before a changed object will be considered for persisted - public long m_persistAfter = DEFAULT_MAX_TIME_FOR_PERSISTENCE * 10000000L; - - protected int m_splitRegionID; - protected Timer m_restartWaitTimer = new Timer(); - protected List m_regionRestartNotifyList = new List(); - protected List m_neighbours = new List(); - protected string m_simulatorVersion = "OpenSimulator Server"; - protected AgentCircuitManager m_authenticateHandler; - protected SceneCommunicationService m_sceneGridService; - - protected ISimulationDataService m_SimulationDataService; - protected IEstateDataService m_EstateDataService; - protected IAssetService m_AssetService; - protected IAuthorizationService m_AuthorizationService; - protected IInventoryService m_InventoryService; - protected IGridService m_GridService; - protected ILibraryService m_LibraryService; - protected ISimulationService m_simulationService; - protected IAuthenticationService m_AuthenticationService; - protected IPresenceService m_PresenceService; - protected IUserAccountService m_UserAccountService; - protected IAvatarService m_AvatarService; - protected IGridUserService m_GridUserService; - - protected IXMLRPC m_xmlrpcModule; - protected IWorldComm m_worldCommModule; - protected IAvatarFactoryModule m_AvatarFactory; - protected IConfigSource m_config; - protected IRegionSerialiserModule m_serialiser; - protected IDialogModule m_dialogModule; - protected ICapabilitiesModule m_capsModule; - protected IGroupsModule m_groupsModule; - - private Dictionary m_extraSettings; - - /// - /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer - /// rather than on a single thread that sleeps. - /// - public bool UpdateOnTimer { get; set; } - - /// - /// Only used if we are updating scene on a timer rather than sleeping a thread. - /// - private Timer m_sceneUpdateTimer; - - /// - /// Current scene frame number - /// - public uint Frame - { - get; - protected set; - } - - /// - /// Current maintenance run number - /// - public uint MaintenanceRun { get; private set; } - - /// - /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we - /// will sleep for the remaining period. - /// - /// - /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations - /// occur too quickly (viewer 1) or with even more slide (viewer 2). - /// - public int MinFrameTicks - { - get { return m_minFrameTicks; } - private set - { - m_minFrameTicks = value; - MinFrameSeconds = (float)m_minFrameTicks / 1000; - } - } - private int m_minFrameTicks; - - /// - /// The minimum length of time in seconds that will be taken for a scene frame. - /// - /// - /// Always derived from MinFrameTicks. - /// - public float MinFrameSeconds { get; private set; } - - /// - /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we - /// will sleep for the remaining period. - /// - /// - /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations - /// occur too quickly (viewer 1) or with even more slide (viewer 2). - /// - public int MinMaintenanceTicks { get; set; } - - private int m_update_physics = 1; - private int m_update_entitymovement = 1; - private int m_update_objects = 1; - private int m_update_presences = 1; // Update scene presence movements - private int m_update_events = 1; - private int m_update_backup = 200; - private int m_update_terrain = 50; -// private int m_update_land = 1; - private int m_update_coarse_locations = 50; - private int m_update_temp_cleaning = 180; - - private int agentMS; - private int frameMS; - private int physicsMS2; - private int physicsMS; - private int otherMS; - private int tempOnRezMS; - private int eventMS; - private int backupMS; - private int terrainMS; - private int landMS; - private int spareMS; - - /// - /// Tick at which the last frame was processed. - /// - private int m_lastFrameTick; - - /// - /// Tick at which the last maintenance run occurred. - /// - private int m_lastMaintenanceTick; - - /// - /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched - /// asynchronously from the update loop. - /// - private bool m_cleaningTemps = false; - - /// - /// Used to control main scene thread looping time when not updating via timer. - /// - private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false); - - /// - /// Used to control maintenance thread runs. - /// - private ManualResetEvent m_maintenanceWaitEvent = new ManualResetEvent(false); - - // TODO: Possibly stop other classes being able to manipulate this directly. - private SceneGraph m_sceneGraph; - private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing - private volatile bool m_backingup; - private Dictionary m_returns = new Dictionary(); - private Dictionary m_groupsWithTargets = new Dictionary(); - - private string m_defaultScriptEngine; - - /// - /// Tick at which the last login occurred. - /// - private int m_LastLogin; - - /// - /// Thread that runs the scene loop. - /// - private Thread m_heartbeatThread; - - /// - /// True if these scene is in the process of shutting down or is shutdown. - /// - public bool ShuttingDown - { - get { return m_shuttingDown; } - } - private volatile bool m_shuttingDown; - - /// - /// Is the scene active? - /// - /// - /// If false, maintenance and update loops are not being run, though after setting to false update may still - /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if - /// the scene is not active. - /// - public bool Active - { - get { return m_active; } - set - { - if (value) - { - if (!m_active) - Start(false); - } - else - { - // This appears assymetric with Start() above but is not - setting m_active = false stops the loops - // XXX: Possibly this should be in an explicit Stop() method for symmetry. - m_active = false; - } - } - } - private volatile bool m_active; - - /// - /// If true then updates are running. This may be true for a short period after a scene is de-activated. - /// - public bool IsRunning { get { return m_isRunning; } } - private volatile bool m_isRunning; - - private Timer m_mapGenerationTimer = new Timer(); - private bool m_generateMaptiles; - - #endregion Fields - - #region Properties - - /* Used by the loadbalancer plugin on GForge */ - public int SplitRegionID - { - get { return m_splitRegionID; } - set { m_splitRegionID = value; } - } - - public new float TimeDilation - { - get { return m_sceneGraph.PhysicsScene.TimeDilation; } - } - - public void setThreadCount(int inUseThreads) - { - // Just pass the thread count information on its way as the Scene - // does not require the value for anything at this time - StatsReporter.SetThreadCount(inUseThreads); - } - - public SceneCommunicationService SceneGridService - { - get { return m_sceneGridService; } - } - - public ISimulationDataService SimulationDataService - { - get - { - if (m_SimulationDataService == null) - { - m_SimulationDataService = RequestModuleInterface(); - - if (m_SimulationDataService == null) - { - throw new Exception("No ISimulationDataService available."); - } - } - - return m_SimulationDataService; - } - } - - public IEstateDataService EstateDataService - { - get - { - if (m_EstateDataService == null) - { - m_EstateDataService = RequestModuleInterface(); - - if (m_EstateDataService == null) - { - throw new Exception("No IEstateDataService available."); - } - } - - return m_EstateDataService; - } - } - - public IAssetService AssetService - { - get - { - if (m_AssetService == null) - { - m_AssetService = RequestModuleInterface(); - - if (m_AssetService == null) - { - throw new Exception("No IAssetService available."); - } - } + public delegate bool FilterAvatarList(ScenePresence avatar); + + public partial class Scene : SceneBase + { + private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; + private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; + + public delegate void SynchronizeSceneHandler(Scene scene); + + #region Fields + + public bool EmergencyMonitoring = false; + + /// + /// Show debug information about animations. + /// + public bool DebugAnimations { get; set; } + + /// + /// Show debug information about teleports. + /// + public bool DebugTeleporting { get; set; } + + /// + /// Show debug information about the scene loop. + /// + public bool DebugUpdates { get; set; } + + /// + /// If true then the scene is saved to persistent storage periodically, every m_update_backup frames and + /// if objects meet required conditions (m_dontPersistBefore and m_dontPersistAfter). + /// + /// + /// Even if false, the scene will still be saved on clean shutdown. + /// FIXME: Currently, setting this to false will mean that objects are not periodically returned from parcels. + /// This needs to be fixed. + /// + public bool PeriodicBackup { get; set; } + + /// + /// If false then the scene is never saved to persistence storage even if PeriodicBackup == true and even + /// if the scene is being shut down for the final time. + /// + public bool UseBackup { get; set; } + + /// + /// If false then physical objects are disabled, though collisions will continue as normal. + /// + public bool PhysicsEnabled + { + get + { + return m_physicsEnabled; + } + + set + { + m_physicsEnabled = value; - return m_AssetService; + if (PhysicsScene != null) + { + IPhysicsParameters physScene = PhysicsScene as IPhysicsParameters; + + if (physScene != null) + physScene.SetPhysicsParameter( + "Active", m_physicsEnabled.ToString(), PhysParameterEntry.APPLY_TO_NONE); + } + } + } + + private bool m_physicsEnabled; + + /// + /// If false then scripts are not enabled on the smiulator + /// + public bool ScriptsEnabled + { + get { return m_scripts_enabled; } + set + { + if (m_scripts_enabled != value) + { + if (!value) + { + m_log.Info("Stopping all Scripts in Scene"); + + EntityBase[] entities = Entities.GetEntities(); + foreach (EntityBase ent in entities) + { + if (ent is SceneObjectGroup) + ((SceneObjectGroup)ent).RemoveScriptInstances(false); + } + } + else + { + m_log.Info("Starting all Scripts in Scene"); + + EntityBase[] entities = Entities.GetEntities(); + foreach (EntityBase ent in entities) + { + if (ent is SceneObjectGroup) + { + SceneObjectGroup sog = (SceneObjectGroup)ent; + sog.CreateScriptInstances(0, false, DefaultScriptEngine, 0); + sog.ResumeScripts(); + } + } + } + + m_scripts_enabled = value; + } + } + } + private bool m_scripts_enabled; + + public SynchronizeSceneHandler SynchronizeScene; + + /// + /// Used to prevent simultaneous calls to code that adds and removes agents. + /// + private object m_removeClientLock = new object(); + + /// + /// Statistical information for this scene. + /// + public SimStatsReporter StatsReporter { get; private set; } + + /// + /// Controls whether physics can be applied to prims. Even if false, prims still have entries in a + /// PhysicsScene in order to perform collision detection + /// + public bool PhysicalPrims { get; private set; } + + /// + /// Controls whether prims can be collided with. + /// + /// + /// If this is set to false then prims cannot be subject to physics either. + /// + public bool CollidablePrims { get; private set; } + + /// + /// Minimum value of the size of a non-physical prim in each axis + /// + public float m_minNonphys = 0.001f; + + /// + /// Maximum value of the size of a non-physical prim in each axis + /// + public float m_maxNonphys = 256; + + /// + /// Minimum value of the size of a physical prim in each axis + /// + public float m_minPhys = 0.01f; + + /// + /// Maximum value of the size of a physical prim in each axis + /// + public float m_maxPhys = 64; + + /// + /// Max prims an object will hold + /// + public int m_linksetCapacity = 0; + + public bool m_clampPrimSize; + public bool m_trustBinaries; + public bool m_allowScriptCrossings = true; + + /// + /// Can avatars cross from and to this region? + /// + public bool AllowAvatarCrossing { get; set; } + + public bool m_useFlySlow; + public bool m_useTrashOnDelete = true; + + /// + /// Temporarily setting to trigger appearance resends at 60 second intervals. + /// + public bool SendPeriodicAppearanceUpdates { get; set; } + + /// + /// How much a root agent has to change position before updates are sent to viewers. + /// + public float RootPositionUpdateTolerance { get; set; } + + /// + /// How much a root agent has to rotate before updates are sent to viewers. + /// + public float RootRotationUpdateTolerance { get; set; } + + /// + /// How much a root agent has to change velocity before updates are sent to viewers. + /// + public float RootVelocityUpdateTolerance { get; set; } + + /// + /// If greater than 1, we only send terse updates to other root agents on every n updates. + /// + public int RootTerseUpdatePeriod { get; set; } + + /// + /// If greater than 1, we only send terse updates to child agents on every n updates. + /// + public int ChildTerseUpdatePeriod { get; set; } + + protected float m_defaultDrawDistance = 255.0f; + public float DefaultDrawDistance + { + // get { return m_defaultDrawDistance; } + get + { + if (RegionInfo != null) + { + float largestDimension = Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); + m_defaultDrawDistance = Math.Max(m_defaultDrawDistance, largestDimension); + + } + return m_defaultDrawDistance; + } + } + + private List m_AllowedViewers = new List(); + private List m_BannedViewers = new List(); + + // TODO: need to figure out how allow client agents but deny + // root agents when ACL denies access to root agent + public bool m_strictAccessControl = true; + + public int MaxUndoCount { get; set; } + + public bool SeeIntoRegion { get; set; } + + // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; + public bool LoginLock = false; + + public bool StartDisabled = false; + public bool LoadingPrims; + public IXfer XferManager; + + // the minimum time that must elapse before a changed object will be considered for persisted + public long m_dontPersistBefore = DEFAULT_MIN_TIME_FOR_PERSISTENCE * 10000000L; + // the maximum time that must elapse before a changed object will be considered for persisted + public long m_persistAfter = DEFAULT_MAX_TIME_FOR_PERSISTENCE * 10000000L; + + protected int m_splitRegionID; + protected Timer m_restartWaitTimer = new Timer(); + protected List m_regionRestartNotifyList = new List(); + protected List m_neighbours = new List(); + protected string m_simulatorVersion = "OpenSimulator Server"; + protected AgentCircuitManager m_authenticateHandler; + protected SceneCommunicationService m_sceneGridService; + + protected ISimulationDataService m_SimulationDataService; + protected IEstateDataService m_EstateDataService; + protected IAssetService m_AssetService; + protected IAuthorizationService m_AuthorizationService; + protected IInventoryService m_InventoryService; + protected IGridService m_GridService; + protected ILibraryService m_LibraryService; + protected ISimulationService m_simulationService; + protected IAuthenticationService m_AuthenticationService; + protected IPresenceService m_PresenceService; + protected IUserAccountService m_UserAccountService; + protected IAvatarService m_AvatarService; + protected IGridUserService m_GridUserService; + + protected IXMLRPC m_xmlrpcModule; + protected IWorldComm m_worldCommModule; + protected IAvatarFactoryModule m_AvatarFactory; + protected IConfigSource m_config; + protected IRegionSerialiserModule m_serialiser; + protected IDialogModule m_dialogModule; + protected ICapabilitiesModule m_capsModule; + protected IGroupsModule m_groupsModule; + + private Dictionary m_extraSettings; + + /// + /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer + /// rather than on a single thread that sleeps. + /// + public bool UpdateOnTimer { get; set; } + + /// + /// Only used if we are updating scene on a timer rather than sleeping a thread. + /// + private Timer m_sceneUpdateTimer; + + /// + /// Current scene frame number + /// + public uint Frame + { + get; + protected set; + } + + /// + /// Current maintenance run number + /// + public uint MaintenanceRun { get; private set; } + + /// + /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we + /// will sleep for the remaining period. + /// + /// + /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations + /// occur too quickly (viewer 1) or with even more slide (viewer 2). + /// + public int MinFrameTicks + { + get { return m_minFrameTicks; } + private set + { + m_minFrameTicks = value; + MinFrameSeconds = (float)m_minFrameTicks / 1000; + } + } + private int m_minFrameTicks; + + /// + /// The minimum length of time in seconds that will be taken for a scene frame. + /// + /// + /// Always derived from MinFrameTicks. + /// + public float MinFrameSeconds { get; private set; } + + /// + /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we + /// will sleep for the remaining period. + /// + /// + /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations + /// occur too quickly (viewer 1) or with even more slide (viewer 2). + /// + public int MinMaintenanceTicks { get; set; } + + private int m_update_physics = 1; + private int m_update_entitymovement = 1; + private int m_update_objects = 1; + private int m_update_presences = 1; // Update scene presence movements + private int m_update_events = 1; + private int m_update_backup = 200; + private int m_update_terrain = 50; + // private int m_update_land = 1; + private int m_update_coarse_locations = 50; + private int m_update_temp_cleaning = 180; + + private int agentMS; + private int frameMS; + private int physicsMS2; + private int physicsMS; + private int otherMS; + private int tempOnRezMS; + private int eventMS; + private int backupMS; + private int terrainMS; + private int landMS; + private int spareMS; + + /// + /// Tick at which the last frame was processed. + /// + private int m_lastFrameTick; + + /// + /// Tick at which the last maintenance run occurred. + /// + private int m_lastMaintenanceTick; + + /// + /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched + /// asynchronously from the update loop. + /// + private bool m_cleaningTemps = false; + + /// + /// Used to control main scene thread looping time when not updating via timer. + /// + private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false); + + /// + /// Used to control maintenance thread runs. + /// + private ManualResetEvent m_maintenanceWaitEvent = new ManualResetEvent(false); + + // TODO: Possibly stop other classes being able to manipulate this directly. + private SceneGraph m_sceneGraph; + private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing + private volatile bool m_backingup; + private Dictionary m_returns = new Dictionary(); + private Dictionary m_groupsWithTargets = new Dictionary(); + + private string m_defaultScriptEngine; + + /// + /// Tick at which the last login occurred. + /// + private int m_LastLogin; + + /// + /// Thread that runs the scene loop. + /// + private Thread m_heartbeatThread; + + /// + /// True if these scene is in the process of shutting down or is shutdown. + /// + public bool ShuttingDown + { + get { return m_shuttingDown; } + } + private volatile bool m_shuttingDown; + + /// + /// Is the scene active? + /// + /// + /// If false, maintenance and update loops are not being run, though after setting to false update may still + /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if + /// the scene is not active. + /// + public bool Active + { + get { return m_active; } + set + { + if (value) + { + if (!m_active) + Start(false); } - } - - public IAuthorizationService AuthorizationService - { - get + else { - if (m_AuthorizationService == null) - { - m_AuthorizationService = RequestModuleInterface(); - - //if (m_AuthorizationService == null) - //{ - // // don't throw an exception if no authorization service is set for the time being - // m_log.InfoFormat("[SCENE]: No Authorization service is configured"); - //} - } - - return m_AuthorizationService; + // This appears assymetric with Start() above but is not - setting m_active = false stops the loops + // XXX: Possibly this should be in an explicit Stop() method for symmetry. + m_active = false; } - } + } + } + private volatile bool m_active; - public IInventoryService InventoryService - { - get - { - if (m_InventoryService == null) - { - m_InventoryService = RequestModuleInterface(); + /// + /// If true then updates are running. This may be true for a short period after a scene is de-activated. + /// + public bool IsRunning { get { return m_isRunning; } } + private volatile bool m_isRunning; - if (m_InventoryService == null) - { - throw new Exception("No IInventoryService available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. Please also check that you have the correct version of your inventory service dll. Sometimes old versions of this dll will still exist. Do a clean checkout and re-create the opensim.ini from the opensim.ini.example."); - } - } + private Timer m_mapGenerationTimer = new Timer(); + private bool m_generateMaptiles; - return m_InventoryService; - } - } + #endregion Fields - public IGridService GridService - { - get - { - if (m_GridService == null) - { - m_GridService = RequestModuleInterface(); + #region Properties - if (m_GridService == null) - { - throw new Exception("No IGridService available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. Please also check that you have the correct version of your inventory service dll. Sometimes old versions of this dll will still exist. Do a clean checkout and re-create the opensim.ini from the opensim.ini.example."); - } - } + /* Used by the loadbalancer plugin on GForge */ + public int SplitRegionID + { + get { return m_splitRegionID; } + set { m_splitRegionID = value; } + } - return m_GridService; - } - } + public new float TimeDilation + { + get { return m_sceneGraph.PhysicsScene.TimeDilation; } + } - public ILibraryService LibraryService - { - get - { - if (m_LibraryService == null) - m_LibraryService = RequestModuleInterface(); + public void setThreadCount(int inUseThreads) + { + // Just pass the thread count information on its way as the Scene + // does not require the value for anything at this time + StatsReporter.SetThreadCount(inUseThreads); + } - return m_LibraryService; - } - } + public SceneCommunicationService SceneGridService + { + get { return m_sceneGridService; } + } - public ISimulationService SimulationService - { - get + public ISimulationDataService SimulationDataService + { + get + { + if (m_SimulationDataService == null) { - if (m_simulationService == null) - m_simulationService = RequestModuleInterface(); + m_SimulationDataService = RequestModuleInterface(); - return m_simulationService; + if (m_SimulationDataService == null) + { + throw new Exception("No ISimulationDataService available."); + } } - } - public IAuthenticationService AuthenticationService - { - get + return m_SimulationDataService; + } + } + + public IEstateDataService EstateDataService + { + get + { + if (m_EstateDataService == null) { - if (m_AuthenticationService == null) - m_AuthenticationService = RequestModuleInterface(); - return m_AuthenticationService; - } - } - - public IPresenceService PresenceService - { - get - { - if (m_PresenceService == null) - m_PresenceService = RequestModuleInterface(); - return m_PresenceService; - } - } + m_EstateDataService = RequestModuleInterface(); - public IUserAccountService UserAccountService - { - get - { - if (m_UserAccountService == null) - m_UserAccountService = RequestModuleInterface(); - return m_UserAccountService; - } - } - - public IAvatarService AvatarService - { - get - { - if (m_AvatarService == null) - m_AvatarService = RequestModuleInterface(); - return m_AvatarService; - } - } - - public IGridUserService GridUserService - { - get - { - if (m_GridUserService == null) - m_GridUserService = RequestModuleInterface(); - return m_GridUserService; - } - } - - public IAttachmentsModule AttachmentsModule { get; set; } - public IEntityTransferModule EntityTransferModule { get; private set; } - public IAgentAssetTransactions AgentTransactionsModule { get; private set; } - public IUserManagement UserManagementModule { get; private set; } - - public IAvatarFactoryModule AvatarFactory - { - get { return m_AvatarFactory; } - } - - public ICapabilitiesModule CapsModule - { - get { return m_capsModule; } - } - - public int MonitorFrameTime { get { return frameMS; } } - public int MonitorPhysicsUpdateTime { get { return physicsMS; } } - public int MonitorPhysicsSyncTime { get { return physicsMS2; } } - public int MonitorOtherTime { get { return otherMS; } } - public int MonitorTempOnRezTime { get { return tempOnRezMS; } } - public int MonitorEventTime { get { return eventMS; } } // This may need to be divided into each event? - public int MonitorBackupTime { get { return backupMS; } } - public int MonitorTerrainTime { get { return terrainMS; } } - public int MonitorLandTime { get { return landMS; } } - public int MonitorLastFrameTick { get { return m_lastFrameTick; } } - - public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } - public bool IsReprioritizationEnabled { get; set; } - public double ReprioritizationInterval { get; set; } - public double RootReprioritizationDistance { get; set; } - public double ChildReprioritizationDistance { get; set; } - - public AgentCircuitManager AuthenticateHandler - { - get { return m_authenticateHandler; } - } - - // an instance to the physics plugin's Scene object. - public PhysicsScene PhysicsScene - { - get { return m_sceneGraph.PhysicsScene; } - set - { - // If we're not doing the initial set - // Then we've got to remove the previous - // event handler - if (PhysicsScene != null && PhysicsScene.SupportsNINJAJoints) - { - PhysicsScene.OnJointMoved -= jointMoved; - PhysicsScene.OnJointDeactivated -= jointDeactivated; - PhysicsScene.OnJointErrorMessage -= jointErrorMessage; - } - - m_sceneGraph.PhysicsScene = value; - - if (PhysicsScene != null && m_sceneGraph.PhysicsScene.SupportsNINJAJoints) - { - // register event handlers to respond to joint movement/deactivation - PhysicsScene.OnJointMoved += jointMoved; - PhysicsScene.OnJointDeactivated += jointDeactivated; - PhysicsScene.OnJointErrorMessage += jointErrorMessage; - } + if (m_EstateDataService == null) + { + throw new Exception("No IEstateDataService available."); + } } - } - - public string DefaultScriptEngine - { - get { return m_defaultScriptEngine; } - } - - public EntityManager Entities - { - get { return m_sceneGraph.Entities; } - } - - - // used in sequence see: SpawnPoint() - private int m_SpawnPoint; - // can be closest/random/sequence - public string SpawnPointRouting - { - get; private set; - } - // allow landmarks to pass - public bool TelehubAllowLandmarks - { - get; private set; - } - #endregion Properties - - #region Constructors + return m_EstateDataService; + } + } + + public IAssetService AssetService + { + get + { + if (m_AssetService == null) + { + m_AssetService = RequestModuleInterface(); + + if (m_AssetService == null) + { + throw new Exception("No IAssetService available."); + } + } + + return m_AssetService; + } + } + + public IAuthorizationService AuthorizationService + { + get + { + if (m_AuthorizationService == null) + { + m_AuthorizationService = RequestModuleInterface(); + + //if (m_AuthorizationService == null) + //{ + // // don't throw an exception if no authorization service is set for the time being + // m_log.InfoFormat("[SCENE]: No Authorization service is configured"); + //} + } + + return m_AuthorizationService; + } + } + + public IInventoryService InventoryService + { + get + { + if (m_InventoryService == null) + { + m_InventoryService = RequestModuleInterface(); + + if (m_InventoryService == null) + { + throw new Exception("No IInventoryService available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. Please also check that you have the correct version of your inventory service dll. Sometimes old versions of this dll will still exist. Do a clean checkout and re-create the opensim.ini from the opensim.ini.example."); + } + } + + return m_InventoryService; + } + } + + public IGridService GridService + { + get + { + if (m_GridService == null) + { + m_GridService = RequestModuleInterface(); + + if (m_GridService == null) + { + throw new Exception("No IGridService available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. Please also check that you have the correct version of your inventory service dll. Sometimes old versions of this dll will still exist. Do a clean checkout and re-create the opensim.ini from the opensim.ini.example."); + } + } + + return m_GridService; + } + } + + public ILibraryService LibraryService + { + get + { + if (m_LibraryService == null) + m_LibraryService = RequestModuleInterface(); + + return m_LibraryService; + } + } + + public ISimulationService SimulationService + { + get + { + if (m_simulationService == null) + m_simulationService = RequestModuleInterface(); + + return m_simulationService; + } + } + + public IAuthenticationService AuthenticationService + { + get + { + if (m_AuthenticationService == null) + m_AuthenticationService = RequestModuleInterface(); + return m_AuthenticationService; + } + } + + public IPresenceService PresenceService + { + get + { + if (m_PresenceService == null) + m_PresenceService = RequestModuleInterface(); + return m_PresenceService; + } + } + + public IUserAccountService UserAccountService + { + get + { + if (m_UserAccountService == null) + m_UserAccountService = RequestModuleInterface(); + return m_UserAccountService; + } + } + + public IAvatarService AvatarService + { + get + { + if (m_AvatarService == null) + m_AvatarService = RequestModuleInterface(); + return m_AvatarService; + } + } + + public IGridUserService GridUserService + { + get + { + if (m_GridUserService == null) + m_GridUserService = RequestModuleInterface(); + return m_GridUserService; + } + } + + public IAttachmentsModule AttachmentsModule { get; set; } + public IEntityTransferModule EntityTransferModule { get; private set; } + public IAgentAssetTransactions AgentTransactionsModule { get; private set; } + public IUserManagement UserManagementModule { get; private set; } + + public IAvatarFactoryModule AvatarFactory + { + get { return m_AvatarFactory; } + } + + public ICapabilitiesModule CapsModule + { + get { return m_capsModule; } + } + + public int MonitorFrameTime { get { return frameMS; } } + public int MonitorPhysicsUpdateTime { get { return physicsMS; } } + public int MonitorPhysicsSyncTime { get { return physicsMS2; } } + public int MonitorOtherTime { get { return otherMS; } } + public int MonitorTempOnRezTime { get { return tempOnRezMS; } } + public int MonitorEventTime { get { return eventMS; } } // This may need to be divided into each event? + public int MonitorBackupTime { get { return backupMS; } } + public int MonitorTerrainTime { get { return terrainMS; } } + public int MonitorLandTime { get { return landMS; } } + public int MonitorLastFrameTick { get { return m_lastFrameTick; } } + + public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } + public bool IsReprioritizationEnabled { get; set; } + public double ReprioritizationInterval { get; set; } + public double RootReprioritizationDistance { get; set; } + public double ChildReprioritizationDistance { get; set; } + + public AgentCircuitManager AuthenticateHandler + { + get { return m_authenticateHandler; } + } + + // an instance to the physics plugin's Scene object. + public PhysicsScene PhysicsScene + { + get { return m_sceneGraph.PhysicsScene; } + set + { + // If we're not doing the initial set + // Then we've got to remove the previous + // event handler + if (PhysicsScene != null && PhysicsScene.SupportsNINJAJoints) + { + PhysicsScene.OnJointMoved -= jointMoved; + PhysicsScene.OnJointDeactivated -= jointDeactivated; + PhysicsScene.OnJointErrorMessage -= jointErrorMessage; + } + + m_sceneGraph.PhysicsScene = value; + + if (PhysicsScene != null && m_sceneGraph.PhysicsScene.SupportsNINJAJoints) + { + // register event handlers to respond to joint movement/deactivation + PhysicsScene.OnJointMoved += jointMoved; + PhysicsScene.OnJointDeactivated += jointDeactivated; + PhysicsScene.OnJointErrorMessage += jointErrorMessage; + } + } + } + + public string DefaultScriptEngine + { + get { return m_defaultScriptEngine; } + } + + public EntityManager Entities + { + get { return m_sceneGraph.Entities; } + } + + + // used in sequence see: SpawnPoint() + private int m_SpawnPoint; + // can be closest/random/sequence + public string SpawnPointRouting + { + get; + private set; + } + // allow landmarks to pass + public bool TelehubAllowLandmarks + { + get; + private set; + } + + #endregion Properties + + #region Constructors + + public Scene(RegionInfo regInfo, AgentCircuitManager authen, PhysicsScene physicsScene, + SceneCommunicationService sceneGridService, + ISimulationDataService simDataService, IEstateDataService estateDataService, + IConfigSource config, string simulatorVersion) + : this(regInfo, physicsScene) + { + m_config = config; + MinFrameTicks = 89; + MinMaintenanceTicks = 1000; + SeeIntoRegion = true; + + Random random = new Random(); + + m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4); + m_authenticateHandler = authen; + m_sceneGridService = sceneGridService; + m_SimulationDataService = simDataService; + m_EstateDataService = estateDataService; + + m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); + m_asyncSceneObjectDeleter.Enabled = true; + + m_asyncInventorySender = new AsyncInventorySender(this); + + #region Region Settings + + // Load region settings + // LoadRegionSettings creates new region settings in persistence if they don't already exist for this region. + // However, in this case, the default textures are not set in memory properly, so we need to do it here and + // resave. + // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new + // region is set up and avoid these gyrations. + RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID); + m_extraSettings = simDataService.GetExtra(RegionInfo.RegionID); + + bool updatedTerrainTextures = false; + if (rs.TerrainTexture1 == UUID.Zero) + { + rs.TerrainTexture1 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_1; + updatedTerrainTextures = true; + } + + if (rs.TerrainTexture2 == UUID.Zero) + { + rs.TerrainTexture2 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_2; + updatedTerrainTextures = true; + } + + if (rs.TerrainTexture3 == UUID.Zero) + { + rs.TerrainTexture3 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_3; + updatedTerrainTextures = true; + } + + if (rs.TerrainTexture4 == UUID.Zero) + { + rs.TerrainTexture4 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_4; + updatedTerrainTextures = true; + } + + if (updatedTerrainTextures) + rs.Save(); + + RegionInfo.RegionSettings = rs; + + if (estateDataService != null) + RegionInfo.EstateSettings = estateDataService.LoadEstateSettings(RegionInfo.RegionID, false); + + #endregion Region Settings + + //Bind Storage Manager functions to some land manager functions for this scene + EventManager.OnLandObjectAdded += + new EventManager.LandObjectAdded(simDataService.StoreLandObject); + EventManager.OnLandObjectRemoved += + new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); + + RegisterDefaultSceneEvents(); + + // XXX: Don't set the public property since we don't want to activate here. This needs to be handled + // better in the future. + m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts; + + PhysicsEnabled = !RegionInfo.RegionSettings.DisablePhysics; + + m_simulatorVersion = simulatorVersion + " (" + Util.GetRuntimeInformation() + ")"; + + #region Region Config + + // Region config overrides global config + // + if (m_config.Configs["Startup"] != null) + { + IConfig startupConfig = m_config.Configs["Startup"]; - public Scene(RegionInfo regInfo, AgentCircuitManager authen, PhysicsScene physicsScene, - SceneCommunicationService sceneGridService, - ISimulationDataService simDataService, IEstateDataService estateDataService, - IConfigSource config, string simulatorVersion) - : this(regInfo, physicsScene) - { - m_config = config; - MinFrameTicks = 89; - MinMaintenanceTicks = 1000; - SeeIntoRegion = true; + StartDisabled = startupConfig.GetBoolean("StartDisabled", false); - Random random = new Random(); - - m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4); - m_authenticateHandler = authen; - m_sceneGridService = sceneGridService; - m_SimulationDataService = simDataService; - m_EstateDataService = estateDataService; + m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); + UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); + if (!UseBackup) + m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); - m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); - m_asyncSceneObjectDeleter.Enabled = true; + //Animation states + m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); - m_asyncInventorySender = new AsyncInventorySender(this); + SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion); - #region Region Settings + MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); - // Load region settings - // LoadRegionSettings creates new region settings in persistence if they don't already exist for this region. - // However, in this case, the default textures are not set in memory properly, so we need to do it here and - // resave. - // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new - // region is set up and avoid these gyrations. - RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID); - m_extraSettings = simDataService.GetExtra(RegionInfo.RegionID); + PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); + CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); - bool updatedTerrainTextures = false; - if (rs.TerrainTexture1 == UUID.Zero) + m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); + if (RegionInfo.NonphysPrimMin > 0) { - rs.TerrainTexture1 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_1; - updatedTerrainTextures = true; + m_minNonphys = RegionInfo.NonphysPrimMin; } - if (rs.TerrainTexture2 == UUID.Zero) + m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); + if (RegionInfo.NonphysPrimMax > 0) { - rs.TerrainTexture2 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_2; - updatedTerrainTextures = true; + m_maxNonphys = RegionInfo.NonphysPrimMax; } - if (rs.TerrainTexture3 == UUID.Zero) + m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys); + if (RegionInfo.PhysPrimMin > 0) { - rs.TerrainTexture3 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_3; - updatedTerrainTextures = true; + m_minPhys = RegionInfo.PhysPrimMin; } - if (rs.TerrainTexture4 == UUID.Zero) + m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); + if (RegionInfo.PhysPrimMax > 0) { - rs.TerrainTexture4 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_4; - updatedTerrainTextures = true; + m_maxPhys = RegionInfo.PhysPrimMax; } - if (updatedTerrainTextures) - rs.Save(); - - RegionInfo.RegionSettings = rs; - - if (estateDataService != null) - RegionInfo.EstateSettings = estateDataService.LoadEstateSettings(RegionInfo.RegionID, false); - - #endregion Region Settings - - //Bind Storage Manager functions to some land manager functions for this scene - EventManager.OnLandObjectAdded += - new EventManager.LandObjectAdded(simDataService.StoreLandObject); - EventManager.OnLandObjectRemoved += - new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); - - RegisterDefaultSceneEvents(); + // Here, if clamping is requested in either global or + // local config, it will be used + // + m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize); + if (RegionInfo.ClampPrimSize) + { + m_clampPrimSize = true; + } - // XXX: Don't set the public property since we don't want to activate here. This needs to be handled - // better in the future. - m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts; + m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); + if (RegionInfo.LinksetCapacity > 0) + { + m_linksetCapacity = RegionInfo.LinksetCapacity; + } - PhysicsEnabled = !RegionInfo.RegionSettings.DisablePhysics; + m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); + m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); + m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); + m_dontPersistBefore = + startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); + m_dontPersistBefore *= 10000000; + m_persistAfter = + startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); + m_persistAfter *= 10000000; - m_simulatorVersion = simulatorVersion + " (" + Util.GetRuntimeInformation() + ")"; + m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); - #region Region Config + SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); + TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); - // Region config overrides global config - // - if (m_config.Configs["Startup"] != null) - { - IConfig startupConfig = m_config.Configs["Startup"]; - - StartDisabled = startupConfig.GetBoolean("StartDisabled", false); - - m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); - UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); - if (!UseBackup) - m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); - - //Animation states - m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); - - SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion); - - MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); - - PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); - CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); - - m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); - if (RegionInfo.NonphysPrimMin > 0) - { - m_minNonphys = RegionInfo.NonphysPrimMin; - } - - m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); - if (RegionInfo.NonphysPrimMax > 0) - { - m_maxNonphys = RegionInfo.NonphysPrimMax; - } - - m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys); - if (RegionInfo.PhysPrimMin > 0) - { - m_minPhys = RegionInfo.PhysPrimMin; - } - - m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); - if (RegionInfo.PhysPrimMax > 0) - { - m_maxPhys = RegionInfo.PhysPrimMax; - } - - // Here, if clamping is requested in either global or - // local config, it will be used - // - m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize); - if (RegionInfo.ClampPrimSize) - { - m_clampPrimSize = true; - } - - m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); - if (RegionInfo.LinksetCapacity > 0) - { - m_linksetCapacity = RegionInfo.LinksetCapacity; - } - - m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); - m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); - m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); - m_dontPersistBefore = - startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); - m_dontPersistBefore *= 10000000; - m_persistAfter = - startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); - m_persistAfter *= 10000000; - - m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); - - SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); - TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); - - m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); - - string[] possibleMapConfigSections = new string[] { "Map", "Startup" }; - - m_generateMaptiles - = Util.GetConfigVarFromSections(config, "GenerateMaptiles", possibleMapConfigSections, true); - - if (m_generateMaptiles) - { - int maptileRefresh = Util.GetConfigVarFromSections(config, "MaptileRefresh", possibleMapConfigSections, 0); - m_log.InfoFormat("[SCENE]: Region {0}, WORLD MAP refresh time set to {1} seconds", RegionInfo.RegionName, maptileRefresh); - if (maptileRefresh != 0) - { - m_mapGenerationTimer.Interval = maptileRefresh * 1000; - m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister; - m_mapGenerationTimer.AutoReset = true; - m_mapGenerationTimer.Start(); - } - } - else - { - string tile - = Util.GetConfigVarFromSections( - config, "MaptileStaticUUID", possibleMapConfigSections, UUID.Zero.ToString()); - - UUID tileID; - - if (tile != UUID.Zero.ToString() && UUID.TryParse(tile, out tileID)) - { - RegionInfo.RegionSettings.TerrainImageID = tileID; - } - else - { - RegionInfo.RegionSettings.TerrainImageID = RegionInfo.MaptileStaticUUID; - m_log.InfoFormat("[SCENE]: Region {0}, maptile set to {1}", RegionInfo.RegionName, RegionInfo.MaptileStaticUUID.ToString()); - } - } - - string[] possibleAccessControlConfigSections = new string[] { "AccessControl", "Startup" }; - - string grant - = Util.GetConfigVarFromSections( - config, "AllowedClients", possibleAccessControlConfigSections, ""); - - if (grant.Length > 0) - { - foreach (string viewer in grant.Split('|')) - { - m_AllowedViewers.Add(viewer.Trim().ToLower()); - } - } - - grant - = Util.GetConfigVarFromSections( - config, "BannedClients", possibleAccessControlConfigSections, ""); - - if (grant.Length > 0) - { - foreach (string viewer in grant.Split('|')) - { - m_BannedViewers.Add(viewer.Trim().ToLower()); - } - } - - if (startupConfig.Contains("MinFrameTime")) - MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000); - - m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup); - m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); - m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement); - m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events); - m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects); - m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics); - m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); - m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); - m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning); - } - - // FIXME: Ultimately this should be in a module. - SendPeriodicAppearanceUpdates = false; - - IConfig appearanceConfig = m_config.Configs["Appearance"]; - if (appearanceConfig != null) - { - SendPeriodicAppearanceUpdates - = appearanceConfig.GetBoolean("ResendAppearanceUpdates", SendPeriodicAppearanceUpdates); - } - - #endregion Region Config - - IConfig entityTransferConfig = m_config.Configs["EntityTransfer"]; - if (entityTransferConfig != null) - { - AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing); - } - - #region Interest Management - - IConfig interestConfig = m_config.Configs["InterestManagement"]; - if (interestConfig != null) - { - string update_prioritization_scheme = interestConfig.GetString("UpdatePrioritizationScheme", "Time").Trim().ToLower(); - - try - { - UpdatePrioritizationScheme = (UpdatePrioritizationSchemes)Enum.Parse(typeof(UpdatePrioritizationSchemes), update_prioritization_scheme, true); - } - catch (Exception) - { - m_log.Warn("[PRIORITIZER]: UpdatePrioritizationScheme was not recognized, setting to default prioritizer Time"); - UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; - } - - IsReprioritizationEnabled - = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled); - ReprioritizationInterval - = interestConfig.GetDouble("ReprioritizationInterval", ReprioritizationInterval); - RootReprioritizationDistance - = interestConfig.GetDouble("RootReprioritizationDistance", RootReprioritizationDistance); - ChildReprioritizationDistance - = interestConfig.GetDouble("ChildReprioritizationDistance", ChildReprioritizationDistance); - - RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod); - ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod); - - RootPositionUpdateTolerance - = interestConfig.GetFloat("RootPositionUpdateTolerance", RootPositionUpdateTolerance); - RootRotationUpdateTolerance - = interestConfig.GetFloat("RootRotationUpdateTolerance", RootRotationUpdateTolerance); - RootVelocityUpdateTolerance - = interestConfig.GetFloat("RootVelocityUpdateTolerance", RootVelocityUpdateTolerance); - } - - m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme); - - #endregion Interest Management + m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); - // The timer used by the Stopwatch class depends on the system hardware and operating system; inform - // if the timer is based on a high-resolution performance counter or based on the system timer; - // the performance counter will provide a more precise time than the system timer - if (Stopwatch.IsHighResolution) - m_log.InfoFormat("[SCENE]: Using high-resolution performance counter for statistics."); - else - m_log.InfoFormat("[SCENE]: Using system timer for statistics."); + string[] possibleMapConfigSections = new string[] { "Map", "Startup" }; - // Acquire the statistics section of the OpenSim.ini file located - // in the bin directory - IConfig statisticsConfig = m_config.Configs["Statistics"]; + m_generateMaptiles + = Util.GetConfigVarFromSections(config, "GenerateMaptiles", possibleMapConfigSections, true); - // Confirm that the statistics section existed in the configuration - // file - if (statisticsConfig != null) + if (m_generateMaptiles) { - // Create the StatsReporter using the number of frames to store - // for the frame time statistics, or 10 frames if the config - // file doesn't contain a value - StatsReporter = new SimStatsReporter(this, - statisticsConfig.GetInt("NumberOfFrames", 10)); + int maptileRefresh = Util.GetConfigVarFromSections(config, "MaptileRefresh", possibleMapConfigSections, 0); + m_log.InfoFormat("[SCENE]: Region {0}, WORLD MAP refresh time set to {1} seconds", RegionInfo.RegionName, maptileRefresh); + if (maptileRefresh != 0) + { + m_mapGenerationTimer.Interval = maptileRefresh * 1000; + m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister; + m_mapGenerationTimer.AutoReset = true; + m_mapGenerationTimer.Start(); + } } else { - // Create a StatsReporter with the current scene and a default - // 10 frames stored for the frame time statistics - StatsReporter = new SimStatsReporter(this); + string tile + = Util.GetConfigVarFromSections( + config, "MaptileStaticUUID", possibleMapConfigSections, UUID.Zero.ToString()); + + UUID tileID; + + if (tile != UUID.Zero.ToString() && UUID.TryParse(tile, out tileID)) + { + RegionInfo.RegionSettings.TerrainImageID = tileID; + } + else + { + RegionInfo.RegionSettings.TerrainImageID = RegionInfo.MaptileStaticUUID; + m_log.InfoFormat("[SCENE]: Region {0}, maptile set to {1}", RegionInfo.RegionName, RegionInfo.MaptileStaticUUID.ToString()); + } } - StatsReporter.OnSendStatsResult += SendSimStatsPackets; - StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; + string[] possibleAccessControlConfigSections = new string[] { "AccessControl", "Startup" }; - } + string grant + = Util.GetConfigVarFromSections( + config, "AllowedClients", possibleAccessControlConfigSections, ""); - public Scene(RegionInfo regInfo, PhysicsScene physicsScene) : base(regInfo) - { - m_sceneGraph = new SceneGraph(this); - m_sceneGraph.PhysicsScene = physicsScene; + if (grant.Length > 0) + { + foreach (string viewer in grant.Split('|')) + { + m_AllowedViewers.Add(viewer.Trim().ToLower()); + } + } - // If the scene graph has an Unrecoverable error, restart this sim. - // Currently the only thing that causes it to happen is two kinds of specific - // Physics based crashes. - // - // Out of memory - // Operating system has killed the plugin - m_sceneGraph.UnRecoverableError - += () => - { - m_log.ErrorFormat("[SCENE]: Restarting region {0} due to unrecoverable physics crash", Name); - RestartNow(); - }; - - PhysicalPrims = true; - CollidablePrims = true; - PhysicsEnabled = true; - - AllowAvatarCrossing = true; - - PeriodicBackup = true; - UseBackup = true; - - IsReprioritizationEnabled = true; - UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; - ReprioritizationInterval = 5000; - - RootRotationUpdateTolerance = 0.1f; - RootVelocityUpdateTolerance = 0.001f; - RootPositionUpdateTolerance = 0.05f; - RootReprioritizationDistance = 10.0; - ChildReprioritizationDistance = 20.0; - - m_eventManager = new EventManager(); - - m_permissions = new ScenePermissions(this); - } - - #endregion - - #region Startup / Close Methods - - /// - /// The scene graph for this scene - /// - /// TODO: Possibly stop other classes being able to manipulate this directly. - public SceneGraph SceneGraph - { - get { return m_sceneGraph; } - } - - protected virtual void RegisterDefaultSceneEvents() - { - IDialogModule dm = RequestModuleInterface(); - - if (dm != null) - m_eventManager.OnPermissionError += dm.SendAlertToUser; - - m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; - } - - public override string GetSimulatorVersion() - { - return m_simulatorVersion; - } - - /// - /// Process the fact that a neighbouring region has come up. - /// - /// - /// We only add it to the neighbor list if it's within 1 region from here. - /// Agents may have draw distance values that cross two regions though, so - /// we add it to the notify list regardless of distance. We'll check - /// the agent's draw distance before notifying them though. - /// - /// RegionInfo handle for the new region. - /// True after all operations complete, throws exceptions otherwise. - public override void OtherRegionUp(GridRegion otherRegion) - { - if (RegionInfo.RegionHandle != otherRegion.RegionHandle) - { - //// If these are cast to INT because long + negative values + abs returns invalid data - //int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX); - //int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY); - //if (resultX <= 1 && resultY <= 1) - float dist = (float)Math.Max(DefaultDrawDistance, - (float)Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY)); - uint newRegionX, newRegionY, thisRegionX, thisRegionY; - Util.RegionHandleToRegionLoc(otherRegion.RegionHandle, out newRegionX, out newRegionY); - Util.RegionHandleToRegionLoc(RegionInfo.RegionHandle, out thisRegionX, out thisRegionY); - - //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", - // RegionInfo.RegionName, otherRegion.RegionName, newRegionX, newRegionY); - - if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY)) - { - // Let the grid service module know, so this can be cached - m_eventManager.TriggerOnRegionUp(otherRegion); - - try - { - ForEachRootScenePresence(delegate(ScenePresence agent) - { - //agent.ControllingClient.new - //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); - - List old = new List(); - old.Add(otherRegion.RegionHandle); - agent.DropOldNeighbours(old); - if (EntityTransferModule != null && agent.PresenceType != PresenceType.Npc) - EntityTransferModule.EnableChildAgent(agent, otherRegion); - }); - } - catch (NullReferenceException) - { - // This means that we're not booted up completely yet. - // This shouldn't happen too often anymore. - m_log.Error("[SCENE]: Couldn't inform client of regionup because we got a null reference exception"); - } - } - else - { - m_log.InfoFormat( - "[SCENE]: Got notice about far away Region: {0} at ({1}, {2})", - otherRegion.RegionName, otherRegion.RegionLocX, otherRegion.RegionLocY); - } - } - } - - public void AddNeighborRegion(RegionInfo region) - { - lock (m_neighbours) - { - if (!CheckNeighborRegion(region)) - { - m_neighbours.Add(region); - } - } - } - - public bool CheckNeighborRegion(RegionInfo region) - { - bool found = false; - lock (m_neighbours) - { - foreach (RegionInfo reg in m_neighbours) - { - if (reg.RegionHandle == region.RegionHandle) - { - found = true; - break; - } - } - } - return found; - } - - // Alias IncomingHelloNeighbour OtherRegionUp, for now - public GridRegion IncomingHelloNeighbour(RegionInfo neighbour) - { - OtherRegionUp(new GridRegion(neighbour)); - return new GridRegion(RegionInfo); - } - - // This causes the region to restart immediatley. - public void RestartNow() - { - IConfig startupConfig = m_config.Configs["Startup"]; - if (startupConfig != null) + grant + = Util.GetConfigVarFromSections( + config, "BannedClients", possibleAccessControlConfigSections, ""); + + if (grant.Length > 0) { - if (startupConfig.GetBoolean("InworldRestartShutsDown", false)) - { - MainConsole.Instance.RunCommand("shutdown"); - return; - } + foreach (string viewer in grant.Split('|')) + { + m_BannedViewers.Add(viewer.Trim().ToLower()); + } } - m_log.InfoFormat("[REGION]: Restarting region {0}", Name); + if (startupConfig.Contains("MinFrameTime")) + MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000); - Close(); + m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup); + m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); + m_update_entitymovement = startupConfig.GetInt("UpdateEntityMovementEveryNFrames", m_update_entitymovement); + m_update_events = startupConfig.GetInt("UpdateEventsEveryNFrames", m_update_events); + m_update_objects = startupConfig.GetInt("UpdateObjectsEveryNFrames", m_update_objects); + m_update_physics = startupConfig.GetInt("UpdatePhysicsEveryNFrames", m_update_physics); + m_update_presences = startupConfig.GetInt("UpdateAgentsEveryNFrames", m_update_presences); + m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain); + m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning); + } - base.Restart(); - } + // FIXME: Ultimately this should be in a module. + SendPeriodicAppearanceUpdates = false; - // This is a helper function that notifies root agents in this region that a new sim near them has come up - // This is in the form of a timer because when an instance of OpenSim.exe is started, - // Even though the sims initialize, they don't listen until 'all of the sims are initialized' - // If we tell an agent about a sim that's not listening yet, the agent will not be able to connect to it. - // subsequently the agent will never see the region come back online. - public void RestartNotifyWaitElapsed(object sender, ElapsedEventArgs e) - { - m_restartWaitTimer.Stop(); - lock (m_regionRestartNotifyList) - { - foreach (RegionInfo region in m_regionRestartNotifyList) - { - GridRegion r = new GridRegion(region); - try - { - ForEachRootScenePresence(delegate(ScenePresence agent) - { - if (EntityTransferModule != null && agent.PresenceType != PresenceType.Npc) - EntityTransferModule.EnableChildAgent(agent, r); - }); - } - catch (NullReferenceException) - { - // This means that we're not booted up completely yet. - // This shouldn't happen too often anymore. - } - } + IConfig appearanceConfig = m_config.Configs["Appearance"]; + if (appearanceConfig != null) + { + SendPeriodicAppearanceUpdates + = appearanceConfig.GetBoolean("ResendAppearanceUpdates", SendPeriodicAppearanceUpdates); + } - // Reset list to nothing. - m_regionRestartNotifyList.Clear(); - } - } + #endregion Region Config + + IConfig entityTransferConfig = m_config.Configs["EntityTransfer"]; + if (entityTransferConfig != null) + { + AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing); + } + + #region Interest Management - public int GetInaccurateNeighborCount() - { - return m_neighbours.Count; - } + IConfig interestConfig = m_config.Configs["InterestManagement"]; + if (interestConfig != null) + { + string update_prioritization_scheme = interestConfig.GetString("UpdatePrioritizationScheme", "Time").Trim().ToLower(); - // This is the method that shuts down the scene. - public override void Close() - { - if (m_shuttingDown) + try { - m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name); - return; + UpdatePrioritizationScheme = (UpdatePrioritizationSchemes)Enum.Parse(typeof(UpdatePrioritizationSchemes), update_prioritization_scheme, true); + } + catch (Exception) + { + m_log.Warn("[PRIORITIZER]: UpdatePrioritizationScheme was not recognized, setting to default prioritizer Time"); + UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; + } + + IsReprioritizationEnabled + = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled); + ReprioritizationInterval + = interestConfig.GetDouble("ReprioritizationInterval", ReprioritizationInterval); + RootReprioritizationDistance + = interestConfig.GetDouble("RootReprioritizationDistance", RootReprioritizationDistance); + ChildReprioritizationDistance + = interestConfig.GetDouble("ChildReprioritizationDistance", ChildReprioritizationDistance); + + RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod); + ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod); + + RootPositionUpdateTolerance + = interestConfig.GetFloat("RootPositionUpdateTolerance", RootPositionUpdateTolerance); + RootRotationUpdateTolerance + = interestConfig.GetFloat("RootRotationUpdateTolerance", RootRotationUpdateTolerance); + RootVelocityUpdateTolerance + = interestConfig.GetFloat("RootVelocityUpdateTolerance", RootVelocityUpdateTolerance); + } + + m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme); + + #endregion Interest Management + + // The timer used by the Stopwatch class depends on the system hardware and operating system; inform + // if the timer is based on a high-resolution performance counter or based on the system timer; + // the performance counter will provide a more precise time than the system timer + if (Stopwatch.IsHighResolution) + m_log.InfoFormat("[SCENE]: Using high-resolution performance counter for statistics."); + else + m_log.InfoFormat("[SCENE]: Using system timer for statistics."); + + // Acquire the statistics section of the OpenSim.ini file located + // in the bin directory + IConfig statisticsConfig = m_config.Configs["Statistics"]; + + // Confirm that the statistics section existed in the configuration + // file + if (statisticsConfig != null) + { + // Create the StatsReporter using the number of frames to store + // for the frame time statistics, or 10 frames if the config + // file doesn't contain a value + StatsReporter = new SimStatsReporter(this, + statisticsConfig.GetInt("NumberOfFrames", 10)); + } + else + { + // Create a StatsReporter with the current scene and a default + // 10 frames stored for the frame time statistics + StatsReporter = new SimStatsReporter(this); + } + + StatsReporter.OnSendStatsResult += SendSimStatsPackets; + StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; + + } + + public Scene(RegionInfo regInfo, PhysicsScene physicsScene) + : base(regInfo) + { + m_sceneGraph = new SceneGraph(this); + m_sceneGraph.PhysicsScene = physicsScene; + + // If the scene graph has an Unrecoverable error, restart this sim. + // Currently the only thing that causes it to happen is two kinds of specific + // Physics based crashes. + // + // Out of memory + // Operating system has killed the plugin + m_sceneGraph.UnRecoverableError + += () => + { + m_log.ErrorFormat("[SCENE]: Restarting region {0} due to unrecoverable physics crash", Name); + RestartNow(); + }; + + PhysicalPrims = true; + CollidablePrims = true; + PhysicsEnabled = true; + + AllowAvatarCrossing = true; + + PeriodicBackup = true; + UseBackup = true; + + IsReprioritizationEnabled = true; + UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; + ReprioritizationInterval = 5000; + + RootRotationUpdateTolerance = 0.1f; + RootVelocityUpdateTolerance = 0.001f; + RootPositionUpdateTolerance = 0.05f; + RootReprioritizationDistance = 10.0; + ChildReprioritizationDistance = 20.0; + + m_eventManager = new EventManager(); + + m_permissions = new ScenePermissions(this); + } + + #endregion + + #region Startup / Close Methods + + /// + /// The scene graph for this scene + /// + /// TODO: Possibly stop other classes being able to manipulate this directly. + public SceneGraph SceneGraph + { + get { return m_sceneGraph; } + } + + protected virtual void RegisterDefaultSceneEvents() + { + IDialogModule dm = RequestModuleInterface(); + + if (dm != null) + m_eventManager.OnPermissionError += dm.SendAlertToUser; + + m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; + } + + public override string GetSimulatorVersion() + { + return m_simulatorVersion; + } + + /// + /// Process the fact that a neighbouring region has come up. + /// + /// + /// We only add it to the neighbor list if it's within 1 region from here. + /// Agents may have draw distance values that cross two regions though, so + /// we add it to the notify list regardless of distance. We'll check + /// the agent's draw distance before notifying them though. + /// + /// RegionInfo handle for the new region. + /// True after all operations complete, throws exceptions otherwise. + public override void OtherRegionUp(GridRegion otherRegion) + { + if (RegionInfo.RegionHandle != otherRegion.RegionHandle) + { + //// If these are cast to INT because long + negative values + abs returns invalid data + //int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX); + //int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY); + //if (resultX <= 1 && resultY <= 1) + float dist = (float)Math.Max(DefaultDrawDistance, + (float)Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY)); + uint newRegionX, newRegionY, thisRegionX, thisRegionY; + Util.RegionHandleToRegionLoc(otherRegion.RegionHandle, out newRegionX, out newRegionY); + Util.RegionHandleToRegionLoc(RegionInfo.RegionHandle, out thisRegionX, out thisRegionY); + + //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", + // RegionInfo.RegionName, otherRegion.RegionName, newRegionX, newRegionY); + + if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY)) + { + // Let the grid service module know, so this can be cached + m_eventManager.TriggerOnRegionUp(otherRegion); + + try + { + ForEachRootScenePresence(delegate(ScenePresence agent) + { + //agent.ControllingClient.new + //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); + + List old = new List(); + old.Add(otherRegion.RegionHandle); + agent.DropOldNeighbours(old); + if (EntityTransferModule != null && agent.PresenceType != PresenceType.Npc) + EntityTransferModule.EnableChildAgent(agent, otherRegion); + }); + } + catch (NullReferenceException) + { + // This means that we're not booted up completely yet. + // This shouldn't happen too often anymore. + m_log.Error("[SCENE]: Couldn't inform client of regionup because we got a null reference exception"); + } } + else + { + m_log.InfoFormat( + "[SCENE]: Got notice about far away Region: {0} at ({1}, {2})", + otherRegion.RegionName, otherRegion.RegionLocX, otherRegion.RegionLocY); + } + } + } + + public void AddNeighborRegion(RegionInfo region) + { + lock (m_neighbours) + { + if (!CheckNeighborRegion(region)) + { + m_neighbours.Add(region); + } + } + } + + public bool CheckNeighborRegion(RegionInfo region) + { + bool found = false; + lock (m_neighbours) + { + foreach (RegionInfo reg in m_neighbours) + { + if (reg.RegionHandle == region.RegionHandle) + { + found = true; + break; + } + } + } + return found; + } + + // Alias IncomingHelloNeighbour OtherRegionUp, for now + public GridRegion IncomingHelloNeighbour(RegionInfo neighbour) + { + OtherRegionUp(new GridRegion(neighbour)); + return new GridRegion(RegionInfo); + } + + // This causes the region to restart immediatley. + public void RestartNow() + { + IConfig startupConfig = m_config.Configs["Startup"]; + if (startupConfig != null) + { + if (startupConfig.GetBoolean("InworldRestartShutsDown", false)) + { + MainConsole.Instance.RunCommand("shutdown"); + return; + } + } + + m_log.InfoFormat("[REGION]: Restarting region {0}", Name); + + Close(); + + base.Restart(); + } + + // This is a helper function that notifies root agents in this region that a new sim near them has come up + // This is in the form of a timer because when an instance of OpenSim.exe is started, + // Even though the sims initialize, they don't listen until 'all of the sims are initialized' + // If we tell an agent about a sim that's not listening yet, the agent will not be able to connect to it. + // subsequently the agent will never see the region come back online. + public void RestartNotifyWaitElapsed(object sender, ElapsedEventArgs e) + { + m_restartWaitTimer.Stop(); + lock (m_regionRestartNotifyList) + { + foreach (RegionInfo region in m_regionRestartNotifyList) + { + GridRegion r = new GridRegion(region); + try + { + ForEachRootScenePresence(delegate(ScenePresence agent) + { + if (EntityTransferModule != null && agent.PresenceType != PresenceType.Npc) + EntityTransferModule.EnableChildAgent(agent, r); + }); + } + catch (NullReferenceException) + { + // This means that we're not booted up completely yet. + // This shouldn't happen too often anymore. + } + } + + // Reset list to nothing. + m_regionRestartNotifyList.Clear(); + } + } + + public int GetInaccurateNeighborCount() + { + return m_neighbours.Count; + } + + // This is the method that shuts down the scene. + public override void Close() + { + if (m_shuttingDown) + { + m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name); + return; + } + + m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); + + StatsReporter.Close(); + + m_restartTimer.Stop(); + m_restartTimer.Close(); + + // Kick all ROOT agents with the message, 'The simulator is going down' + ForEachScenePresence(delegate(ScenePresence avatar) + { + avatar.RemoveNeighbourRegion(RegionInfo.RegionHandle); + + if (!avatar.IsChildAgent) + avatar.ControllingClient.Kick("The simulator is going down."); + + avatar.ControllingClient.SendShutdownConnectionNotice(); + }); + + // Stop updating the scene objects and agents. + m_shuttingDown = true; + + // Wait here, or the kick messages won't actually get to the agents before the scene terminates. + // We also need to wait to avoid a race condition with the scene update loop which might not yet + // have checked ShuttingDown. + Thread.Sleep(500); + + // Stop all client threads. + ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); + + m_log.Debug("[SCENE]: Persisting changed objects"); + EventManager.TriggerSceneShuttingDown(this); + Backup(false); + m_sceneGraph.Close(); + + if (!GridService.DeregisterRegion(RegionInfo.RegionID)) + m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); + + base.Close(); + + // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence. + // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can + // attempt to reference a null or disposed physics scene. + if (PhysicsScene != null) + { + PhysicsScene phys = PhysicsScene; + // remove the physics engine from both Scene and SceneGraph + PhysicsScene = null; + phys.Dispose(); + phys = null; + } + } + + public override void Start() + { + Start(true); + } + + /// + /// Start the scene + /// + /// + /// Start the scripts within the scene. + /// + public void Start(bool startScripts) + { + if (IsRunning) + return; + + m_isRunning = true; + m_active = true; + + // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); + if (m_heartbeatThread != null) + { + m_heartbeatThread.Abort(); + m_heartbeatThread = null; + } + + m_heartbeatThread + = WorkManager.StartThread( + Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); + + StartScripts(); + } + + /// + /// Sets up references to modules required by the scene + /// + public void SetModuleInterfaces() + { + m_xmlrpcModule = RequestModuleInterface(); + m_worldCommModule = RequestModuleInterface(); + XferManager = RequestModuleInterface(); + m_AvatarFactory = RequestModuleInterface(); + AttachmentsModule = RequestModuleInterface(); + m_serialiser = RequestModuleInterface(); + m_dialogModule = RequestModuleInterface(); + m_capsModule = RequestModuleInterface(); + EntityTransferModule = RequestModuleInterface(); + m_groupsModule = RequestModuleInterface(); + AgentTransactionsModule = RequestModuleInterface(); + UserManagementModule = RequestModuleInterface(); + } + + #endregion + + #region Update Methods + + /// + /// Activate the various loops necessary to continually update the scene. + /// + private void Heartbeat() + { + m_eventManager.TriggerOnRegionStarted(this); + + // The first frame can take a very long time due to physics actors being added on startup. Therefore, + // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false + // alarms for scenes with many objects. + Update(1); + + WorkManager.StartThread( + Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); + + Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; + m_lastFrameTick = Util.EnvironmentTickCount(); + + if (UpdateOnTimer) + { + m_sceneUpdateTimer = new Timer(MinFrameTicks); + m_sceneUpdateTimer.AutoReset = true; + m_sceneUpdateTimer.Elapsed += Update; + m_sceneUpdateTimer.Start(); + } + else + { + Thread.CurrentThread.Priority = ThreadPriority.Highest; + Update(-1); + Watchdog.RemoveThread(); + m_isRunning = false; + } + } - m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); + private volatile bool m_isTimerUpdateRunning; - StatsReporter.Close(); + private void Update(object sender, ElapsedEventArgs e) + { + if (m_isTimerUpdateRunning) + return; - m_restartTimer.Stop(); - m_restartTimer.Close(); + m_isTimerUpdateRunning = true; - // Kick all ROOT agents with the message, 'The simulator is going down' - ForEachScenePresence(delegate(ScenePresence avatar) - { - avatar.RemoveNeighbourRegion(RegionInfo.RegionHandle); + // If the last frame did not complete on time, then immediately start the next update on the same thread + // and ignore further timed updates until we have a frame that had spare time. + while (!Update(1) && Active) { } - if (!avatar.IsChildAgent) - avatar.ControllingClient.Kick("The simulator is going down."); + if (!Active || m_shuttingDown) + { + m_sceneUpdateTimer.Stop(); + m_sceneUpdateTimer = null; + m_isRunning = false; + } - avatar.ControllingClient.SendShutdownConnectionNotice(); - }); + m_isTimerUpdateRunning = false; + } - // Stop updating the scene objects and agents. - m_shuttingDown = true; + private void Maintenance() + { + DoMaintenance(-1); - // Wait here, or the kick messages won't actually get to the agents before the scene terminates. - // We also need to wait to avoid a race condition with the scene update loop which might not yet - // have checked ShuttingDown. - Thread.Sleep(500); + Watchdog.RemoveThread(); + } - // Stop all client threads. - ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); + public void DoMaintenance(int runs) + { + long? endRun = null; + int runtc, tmpMS; + int previousMaintenanceTick; - m_log.Debug("[SCENE]: Persisting changed objects"); - EventManager.TriggerSceneShuttingDown(this); - Backup(false); - m_sceneGraph.Close(); + if (runs >= 0) + endRun = MaintenanceRun + runs; - if (!GridService.DeregisterRegion(RegionInfo.RegionID)) - m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); + List coarseLocations; + List avatarUUIDs; - base.Close(); + while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) + { + runtc = Util.EnvironmentTickCount(); + ++MaintenanceRun; - // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence. - // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can - // attempt to reference a null or disposed physics scene. - if (PhysicsScene != null) + // m_log.DebugFormat("[SCENE]: Maintenance run {0} in {1}", MaintenanceRun, Name); + + // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) + if (MaintenanceRun % (m_update_coarse_locations / 10) == 0) { - PhysicsScene phys = PhysicsScene; - // remove the physics engine from both Scene and SceneGraph - PhysicsScene = null; - phys.Dispose(); - phys = null; - } - } - - public override void Start() - { - Start(true); - } - - /// - /// Start the scene - /// - /// - /// Start the scripts within the scene. - /// - public void Start(bool startScripts) - { - if (IsRunning) - return; - - m_isRunning = true; - m_active = true; - -// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); - if (m_heartbeatThread != null) - { - m_heartbeatThread.Abort(); - m_heartbeatThread = null; - } - - m_heartbeatThread - = WorkManager.StartThread( - Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); - - StartScripts(); - } - - /// - /// Sets up references to modules required by the scene - /// - public void SetModuleInterfaces() - { - m_xmlrpcModule = RequestModuleInterface(); - m_worldCommModule = RequestModuleInterface(); - XferManager = RequestModuleInterface(); - m_AvatarFactory = RequestModuleInterface(); - AttachmentsModule = RequestModuleInterface(); - m_serialiser = RequestModuleInterface(); - m_dialogModule = RequestModuleInterface(); - m_capsModule = RequestModuleInterface(); - EntityTransferModule = RequestModuleInterface(); - m_groupsModule = RequestModuleInterface(); - AgentTransactionsModule = RequestModuleInterface(); - UserManagementModule = RequestModuleInterface(); - } - - #endregion - - #region Update Methods - - /// - /// Activate the various loops necessary to continually update the scene. - /// - private void Heartbeat() - { - m_eventManager.TriggerOnRegionStarted(this); - - // The first frame can take a very long time due to physics actors being added on startup. Therefore, - // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false - // alarms for scenes with many objects. - Update(1); - - WorkManager.StartThread( - Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); - - Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; - m_lastFrameTick = Util.EnvironmentTickCount(); + SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); + // Send coarse locations to clients + ForEachScenePresence(delegate(ScenePresence presence) + { + presence.SendCoarseLocations(coarseLocations, avatarUUIDs); + }); + } - if (UpdateOnTimer) + if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0) { - m_sceneUpdateTimer = new Timer(MinFrameTicks); - m_sceneUpdateTimer.AutoReset = true; - m_sceneUpdateTimer.Elapsed += Update; - m_sceneUpdateTimer.Start(); + // m_log.DebugFormat("[SCENE]: Sending periodic appearance updates"); + + if (AvatarFactory != null) + { + ForEachRootScenePresence(sp => AvatarFactory.SendAppearance(sp.UUID)); + } } - else + + // Delete temp-on-rez stuff + if (MaintenanceRun % m_update_temp_cleaning == 0 && !m_cleaningTemps) { - Thread.CurrentThread.Priority = ThreadPriority.Highest; - Update(-1); - Watchdog.RemoveThread(); - m_isRunning = false; + // m_log.DebugFormat("[SCENE]: Running temp-on-rez cleaning in {0}", Name); + tmpMS = Util.EnvironmentTickCount(); + m_cleaningTemps = true; + + WorkManager.RunInThread( + delegate { CleanTempObjects(); m_cleaningTemps = false; }, + null, + string.Format("CleanTempObjects ({0})", Name)); + + tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS); } - } - private volatile bool m_isTimerUpdateRunning; + Watchdog.UpdateThread(); - private void Update(object sender, ElapsedEventArgs e) - { - if (m_isTimerUpdateRunning) - return; + previousMaintenanceTick = m_lastMaintenanceTick; + m_lastMaintenanceTick = Util.EnvironmentTickCount(); + runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); + runtc = MinMaintenanceTicks - runtc; - m_isTimerUpdateRunning = true; + if (runtc > 0) + m_maintenanceWaitEvent.WaitOne(runtc); - // If the last frame did not complete on time, then immediately start the next update on the same thread - // and ignore further timed updates until we have a frame that had spare time. - while (!Update(1) && Active) {} + // Optionally warn if a frame takes double the amount of time that it should. + if (DebugUpdates + && Util.EnvironmentTickCountSubtract( + m_lastMaintenanceTick, previousMaintenanceTick) > MinMaintenanceTicks * 2) + m_log.WarnFormat( + "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", + Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), + MinMaintenanceTicks, + RegionInfo.RegionName); + } + } - if (!Active || m_shuttingDown) - { - m_sceneUpdateTimer.Stop(); - m_sceneUpdateTimer = null; - m_isRunning = false; - } + public override bool Update(int frames) + { + long? endFrame = null; - m_isTimerUpdateRunning = false; - } + if (frames >= 0) + endFrame = Frame + frames; - private void Maintenance() - { - DoMaintenance(-1); + float physicsFPS = 0f; + int previousFrameTick, tmpMS; - Watchdog.RemoveThread(); - } - - public void DoMaintenance(int runs) - { - long? endRun = null; - int runtc, tmpMS; - int previousMaintenanceTick; - - if (runs >= 0) - endRun = MaintenanceRun + runs; - - List coarseLocations; - List avatarUUIDs; - - while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) - { - runtc = Util.EnvironmentTickCount(); - ++MaintenanceRun; - -// m_log.DebugFormat("[SCENE]: Maintenance run {0} in {1}", MaintenanceRun, Name); - - // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) - if (MaintenanceRun % (m_update_coarse_locations / 10) == 0) - { - SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); - // Send coarse locations to clients - ForEachScenePresence(delegate(ScenePresence presence) - { - presence.SendCoarseLocations(coarseLocations, avatarUUIDs); - }); - } - - if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0) - { -// m_log.DebugFormat("[SCENE]: Sending periodic appearance updates"); - - if (AvatarFactory != null) - { - ForEachRootScenePresence(sp => AvatarFactory.SendAppearance(sp.UUID)); - } - } - - // Delete temp-on-rez stuff - if (MaintenanceRun % m_update_temp_cleaning == 0 && !m_cleaningTemps) - { -// m_log.DebugFormat("[SCENE]: Running temp-on-rez cleaning in {0}", Name); - tmpMS = Util.EnvironmentTickCount(); - m_cleaningTemps = true; - - WorkManager.RunInThread( - delegate { CleanTempObjects(); m_cleaningTemps = false; }, - null, - string.Format("CleanTempObjects ({0})", Name)); - - tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS); - } - - Watchdog.UpdateThread(); - - previousMaintenanceTick = m_lastMaintenanceTick; - m_lastMaintenanceTick = Util.EnvironmentTickCount(); - runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); - runtc = MinMaintenanceTicks - runtc; - - if (runtc > 0) - m_maintenanceWaitEvent.WaitOne(runtc); - - // Optionally warn if a frame takes double the amount of time that it should. - if (DebugUpdates - && Util.EnvironmentTickCountSubtract( - m_lastMaintenanceTick, previousMaintenanceTick) > MinMaintenanceTicks * 2) - m_log.WarnFormat( - "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", - Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), - MinMaintenanceTicks, - RegionInfo.RegionName); - } - } - - public override bool Update(int frames) - { - long? endFrame = null; - - if (frames >= 0) - endFrame = Frame + frames; - - float physicsFPS = 0f; - int previousFrameTick, tmpMS; - - // These variables will be used to save the precise frame time using the - // Stopwatch class of Microsoft SDK; the times are recorded at the start - // and end of a parcticular section of code, and then used to calculate - // the frame times, which are the sums of the sections for each given name - double preciseTotalFrameTime = 0.0; - double preciseSimFrameTime = 0.0; - double precisePhysicsFrameTime = 0.0; - Stopwatch totalFrameStopwatch = new Stopwatch(); - Stopwatch simFrameStopwatch = new Stopwatch(); - Stopwatch physicsFrameStopwatch = new Stopwatch(); - - // Begin the stopwatch to keep track of the time that the frame - // started running to determine how long the frame took to complete - totalFrameStopwatch.Start(); - - while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) - { - ++Frame; - -// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); - - agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; - - try - { - EventManager.TriggerRegionHeartbeatStart(this); - - // Apply taints in terrain module to terrain in physics scene - if (Frame % m_update_terrain == 0) - { - tmpMS = Util.EnvironmentTickCount(); - UpdateTerrain(); - terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); - } - - // At several points inside the code there was a need to - // create a more precise measurement of time elapsed. This - // led to the addition of variables that have a similar - // function and thus remain tightly connected to their - // original counterparts. However, the original code is - // not receiving comments from our group because we don't - // feel right modifying the code to that degree at this - // point in time, the precise values all begin with the - // keyword precise - - tmpMS = Util.EnvironmentTickCount(); - - // Begin the stopwatch to track the time to prepare physics - physicsFrameStopwatch.Start(); - if (PhysicsEnabled && Frame % m_update_physics == 0) - m_sceneGraph.UpdatePreparePhysics(); - - // Get the time it took to prepare the physics, this - // would report the most precise time that physics was - // running on the machine and should the physics not be - // enabled will report the time it took to check if physics - // was enabled - physicsFrameStopwatch.Stop(); - precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds; - physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); - - // Apply any pending avatar force input to the avatar's velocity - tmpMS = Util.EnvironmentTickCount(); - simFrameStopwatch.Start(); - if (Frame % m_update_entitymovement == 0) - m_sceneGraph.UpdateScenePresenceMovement(); - - // Get the simulation frame time that the avatar force input took - simFrameStopwatch.Stop(); - preciseSimFrameTime = simFrameStopwatch.Elapsed.TotalMilliseconds; - agentMS = Util.EnvironmentTickCountSubtract(tmpMS); - - // Perform the main physics update. This will do the actual work of moving objects and avatars according to their - // velocity - tmpMS = Util.EnvironmentTickCount(); - physicsFrameStopwatch.Restart(); - if (Frame % m_update_physics == 0) - { - if (PhysicsEnabled) - physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds); - - if (SynchronizeScene != null) - SynchronizeScene(this); - } - - // Add the main physics update time to the prepare physics time - physicsFrameStopwatch.Stop(); - precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; - physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); - - // Start the stopwatch for the remainder of the simulation - simFrameStopwatch.Restart(); - tmpMS = Util.EnvironmentTickCount(); - - // Check if any objects have reached their targets - CheckAtTargets(); - - // Update SceneObjectGroups that have scheduled themselves for updates - // Objects queue their updates onto all scene presences - if (Frame % m_update_objects == 0) - m_sceneGraph.UpdateObjectGroups(); - - // Run through all ScenePresences looking for updates - // Presence updates and queued object updates for each presence are sent to clients - if (Frame % m_update_presences == 0) - m_sceneGraph.UpdatePresences(); - - agentMS += Util.EnvironmentTickCountSubtract(tmpMS); - - if (Frame % m_update_events == 0) - { - tmpMS = Util.EnvironmentTickCount(); - UpdateEvents(); - eventMS = Util.EnvironmentTickCountSubtract(tmpMS); - } - - if (PeriodicBackup && Frame % m_update_backup == 0) - { - tmpMS = Util.EnvironmentTickCount(); - UpdateStorageBackup(); - backupMS = Util.EnvironmentTickCountSubtract(tmpMS); - } - - //if (Frame % m_update_land == 0) - //{ - // int ldMS = Util.EnvironmentTickCount(); - // UpdateLand(); - // landMS = Util.EnvironmentTickCountSubtract(ldMS); - //} - - if (!LoginsEnabled && Frame == 20) - { - // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); - - // In 99.9% of cases it is a bad idea to manually force garbage collection. However, - // this is a rare case where we know we have just went through a long cycle of heap - // allocations, and there is no more work to be done until someone logs in - GC.Collect(); - - if (!LoginLock) - { - if (!StartDisabled) - { - m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); - LoginsEnabled = true; - } - - m_sceneGridService.InformNeighborsThatRegionisUp( - RequestModuleInterface(), RegionInfo); - - // Region ready should always be set - Ready = true; - } - else - { - // This handles a case of a region having no scripts for the RegionReady module - if (m_sceneGraph.GetActiveScriptsCount() == 0) - { - // In this case, we leave it to the IRegionReadyModule to enable logins - - // LoginLock can currently only be set by a region module implementation. - // If somehow this hasn't been done then the quickest way to bugfix is to see the - // NullReferenceException - IRegionReadyModule rrm = RequestModuleInterface(); - rrm.TriggerRegionReady(this); - } - } - } - } - catch (Exception e) - { - m_log.ErrorFormat( - "[SCENE]: Failed on region {0} with exception {1}{2}", - RegionInfo.RegionName, e.Message, e.StackTrace); - } - - EventManager.TriggerRegionHeartbeatEnd(this); - otherMS = eventMS + backupMS + terrainMS + landMS; - - if (!UpdateOnTimer) - { - Watchdog.UpdateThread(); - - spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick); - - if (spareMS > 0) - m_updateWaitEvent.WaitOne(spareMS); - else - spareMS = 0; - } - else - { - spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); - } - - // Get the elapsed time for the simulation frame - simFrameStopwatch.Stop(); - preciseSimFrameTime += simFrameStopwatch.Elapsed.TotalMilliseconds; - - previousFrameTick = m_lastFrameTick; - frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); - m_lastFrameTick = Util.EnvironmentTickCount(); - - // if (Frame%m_update_avatars == 0) - // UpdateInWorldTime(); - StatsReporter.AddPhysicsFPS(physicsFPS); - StatsReporter.AddTimeDilation(TimeDilation); - StatsReporter.AddFPS(1); - - StatsReporter.addFrameMS(frameMS); - StatsReporter.addAgentMS(agentMS); - StatsReporter.addPhysicsMS(physicsMS + physicsMS2); - StatsReporter.addOtherMS(otherMS); - StatsReporter.AddSpareMS(spareMS); - StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); - - // Send the correct time values to the stats reporter for the - // frame times - StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime, - preciseSimFrameTime, precisePhysicsFrameTime, 0.0); - - // Send the correct number of frames that the physics library - // has processed to the stats reporter - StatsReporter.addPhysicsFrame(1); - - // Optionally warn if a frame takes double the amount of time that it should. - if (DebugUpdates - && Util.EnvironmentTickCountSubtract( - m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2) - m_log.WarnFormat( - "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", - Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), - MinFrameTicks, - RegionInfo.RegionName); - } - - // Finished updating scene frame, so stop the total frame's Stopwatch - totalFrameStopwatch.Stop(); + // These variables will be used to save the precise frame time using the + // Stopwatch class of Microsoft SDK; the times are recorded at the start + // and end of a parcticular section of code, and then used to calculate + // the frame times, which are the sums of the sections for each given name + double preciseTotalFrameTime = 0.0; + double preciseSimFrameTime = 0.0; + double precisePhysicsFrameTime = 0.0; + Stopwatch totalFrameStopwatch = new Stopwatch(); + Stopwatch simFrameStopwatch = new Stopwatch(); + Stopwatch physicsFrameStopwatch = new Stopwatch(); + + // Begin the stopwatch to keep track of the time that the frame + // started running to determine how long the frame took to complete + totalFrameStopwatch.Start(); + + while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) + { + ++Frame; + + // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); + + agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; - return spareMS >= 0; - } - - public void AddGroupTarget(SceneObjectGroup grp) - { - lock (m_groupsWithTargets) - m_groupsWithTargets[grp.UUID] = grp; - } - - public void RemoveGroupTarget(SceneObjectGroup grp) - { - lock (m_groupsWithTargets) - m_groupsWithTargets.Remove(grp.UUID); - } - - private void CheckAtTargets() - { - List objs = null; - - lock (m_groupsWithTargets) - { - if (m_groupsWithTargets.Count != 0) - objs = new List(m_groupsWithTargets.Values); - } - - if (objs != null) - { - foreach (SceneObjectGroup entry in objs) - entry.checkAtTargets(); - } - } - - /// - /// Send out simstats data to all clients - /// - /// Stats on the Simulator's performance - private void SendSimStatsPackets(SimStats stats) - { - ForEachRootClient(delegate(IClientAPI client) - { - client.SendSimStats(stats); - }); - } - - /// - /// Update the terrain if it needs to be updated. - /// - private void UpdateTerrain() - { - EventManager.TriggerTerrainTick(); - } - - /// - /// Back up queued up changes - /// - private void UpdateStorageBackup() - { - if (!m_backingup) - { - m_backingup = true; - WorkManager.RunInThread(o => Backup(false), null, string.Format("BackupWaitCallback ({0})", Name)); - } - } - - /// - /// Sends out the OnFrame event to the modules - /// - private void UpdateEvents() - { - m_eventManager.TriggerOnFrame(); - } - - /// - /// Backup the scene. - /// - /// - /// This acts as the main method of the backup thread. In a regression test whether the backup thread is not - /// running independently this can be invoked directly. - /// - /// - /// If true, then any changes that have not yet been persisted are persisted. If false, - /// then the persistence decision is left to the backup code (in some situations, such as object persistence, - /// it's much more efficient to backup multiple changes at once rather than every single one). - /// - public void Backup(bool forced) - { - lock (m_returns) - { - EventManager.TriggerOnBackup(SimulationDataService, forced); - m_backingup = false; - - foreach (KeyValuePair ret in m_returns) - { - UUID transaction = UUID.Random(); - - GridInstantMessage msg = new GridInstantMessage(); - msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server - msg.toAgentID = new Guid(ret.Key.ToString()); - msg.imSessionID = new Guid(transaction.ToString()); - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - msg.fromAgentName = "Server"; - msg.dialog = (byte)19; // Object msg - msg.fromGroup = false; - msg.offline = (byte)0; - msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; - msg.Position = Vector3.Zero; - msg.RegionID = RegionInfo.RegionID.Guid; - - // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3. - msg.binaryBucket = Util.StringToBytes256("\0"); - if (ret.Value.count > 1) - msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); - else - msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); - - IMessageTransferModule tr = RequestModuleInterface(); - if (tr != null) - tr.SendInstantMessage(msg, delegate(bool success) {}); - } - m_returns.Clear(); - } - } - - /// - /// Synchronous force backup. For deletes and links/unlinks - /// - /// Object to be backed up - public void ForceSceneObjectBackup(SceneObjectGroup group) - { - if (group != null) - { - group.HasGroupChanged = true; - group.ProcessBackup(SimulationDataService, true); - } - } - - /// - /// Tell an agent that their object has been returned. - /// - /// - /// The actual return is handled by the caller. - /// - /// Avatar Unique Id - /// Name of object returned - /// Location of object returned - /// Reasion for object return - public void AddReturn(UUID agentID, string objectName, Vector3 location, string reason) - { - lock (m_returns) - { - if (m_returns.ContainsKey(agentID)) - { - ReturnInfo info = m_returns[agentID]; - info.count++; - m_returns[agentID] = info; - } - else - { - ReturnInfo info = new ReturnInfo(); - info.count = 1; - info.objectName = objectName; - info.location = location; - info.reason = reason; - m_returns[agentID] = info; - } - } - } - - #endregion - - #region Load Terrain - - /// - /// Store the terrain in the persistant data store - /// - public void SaveTerrain() - { - SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); - } - - public void StoreWindlightProfile(RegionLightShareData wl) - { - RegionInfo.WindlightSettings = wl; - SimulationDataService.StoreRegionWindlightSettings(wl); - m_eventManager.TriggerOnSaveNewWindlightProfile(); - } - - public void LoadWindlightProfile() - { - RegionInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(RegionInfo.RegionID); - m_eventManager.TriggerOnSaveNewWindlightProfile(); - } - - /// - /// Loads the World heightmap - /// - public override void LoadWorldMap() - { try { - TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); - if (map == null) - { - // This should be in the Terrain module, but it isn't because - // the heightmap is needed _way_ before the modules are initialized... - IConfig terrainConfig = m_config.Configs["Terrain"]; - String m_InitialTerrain = "pinhead-island"; - if (terrainConfig != null) - m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); - - m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); - Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); - - SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); - } - else - { - Heightmap = new TerrainChannel(map); - } - } - catch (IOException e) - { - m_log.WarnFormat( - "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}", - e.Message, e.StackTrace); - - // Non standard region size. If there's an old terrain in the database, it might read past the buffer - #pragma warning disable 0162 - if ((int)Constants.RegionSize != 256) - { - Heightmap = new TerrainChannel(); - - SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); - } + EventManager.TriggerRegionHeartbeatStart(this); + + // Apply taints in terrain module to terrain in physics scene + if (Frame % m_update_terrain == 0) + { + tmpMS = Util.EnvironmentTickCount(); + simFrameStopwatch.Start(); + UpdateTerrain(); + + // Get the simulation frame time that the avatar force + // input took + simFrameStopwatch.Stop(); + preciseSimFrameTime = + simFrameStopwatch.Elapsed.TotalMilliseconds; + terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); + } + + // At several points inside the code there was a need to + // create a more precise measurement of time elapsed. This + // led to the addition of variables that have a similar + // function and thus remain tightly connected to their + // original counterparts. However, the original code is + // not receiving comments from our group because we don't + // feel right modifying the code to that degree at this + // point in time, the precise values all begin with the + // keyword precise + + tmpMS = Util.EnvironmentTickCount(); + + // Begin the stopwatch to track the time to prepare physics + physicsFrameStopwatch.Start(); + if (PhysicsEnabled && Frame % m_update_physics == 0) + m_sceneGraph.UpdatePreparePhysics(); + + // Get the time it took to prepare the physics, this + // would report the most precise time that physics was + // running on the machine and should the physics not be + // enabled will report the time it took to check if physics + // was enabled + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds; + physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); + + // Apply any pending avatar force input to the avatar's velocity + tmpMS = Util.EnvironmentTickCount(); + simFrameStopwatch.Restart(); + if (Frame % m_update_entitymovement == 0) + m_sceneGraph.UpdateScenePresenceMovement(); + + // Get the simulation frame time that the avatar force input + // took + simFrameStopwatch.Stop(); + preciseSimFrameTime += + simFrameStopwatch.Elapsed.TotalMilliseconds; + agentMS = Util.EnvironmentTickCountSubtract(tmpMS); + + // Perform the main physics update. This will do the actual work of moving objects and avatars according to their + // velocity + tmpMS = Util.EnvironmentTickCount(); + physicsFrameStopwatch.Restart(); + if (Frame % m_update_physics == 0) + { + if (PhysicsEnabled) + physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds); + + if (SynchronizeScene != null) + SynchronizeScene(this); + } + + // Add the main physics update time to the prepare physics time + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; + physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); + + // Start the stopwatch for the remainder of the simulation + simFrameStopwatch.Restart(); + tmpMS = Util.EnvironmentTickCount(); + + // Check if any objects have reached their targets + CheckAtTargets(); + + // Update SceneObjectGroups that have scheduled themselves for updates + // Objects queue their updates onto all scene presences + if (Frame % m_update_objects == 0) + m_sceneGraph.UpdateObjectGroups(); + + // Run through all ScenePresences looking for updates + // Presence updates and queued object updates for each presence are sent to clients + if (Frame % m_update_presences == 0) + m_sceneGraph.UpdatePresences(); + + agentMS += Util.EnvironmentTickCountSubtract(tmpMS); + + if (Frame % m_update_events == 0) + { + tmpMS = Util.EnvironmentTickCount(); + UpdateEvents(); + eventMS = Util.EnvironmentTickCountSubtract(tmpMS); + } + + if (PeriodicBackup && Frame % m_update_backup == 0) + { + tmpMS = Util.EnvironmentTickCount(); + UpdateStorageBackup(); + backupMS = Util.EnvironmentTickCountSubtract(tmpMS); + } + + //if (Frame % m_update_land == 0) + //{ + // int ldMS = Util.EnvironmentTickCount(); + // UpdateLand(); + // landMS = Util.EnvironmentTickCountSubtract(ldMS); + //} + + if (!LoginsEnabled && Frame == 20) + { + // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); + + // In 99.9% of cases it is a bad idea to manually force garbage collection. However, + // this is a rare case where we know we have just went through a long cycle of heap + // allocations, and there is no more work to be done until someone logs in + GC.Collect(); + + if (!LoginLock) + { + if (!StartDisabled) + { + m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); + LoginsEnabled = true; + } + + m_sceneGridService.InformNeighborsThatRegionisUp( + RequestModuleInterface(), RegionInfo); + + // Region ready should always be set + Ready = true; + } + else + { + // This handles a case of a region having no scripts for the RegionReady module + if (m_sceneGraph.GetActiveScriptsCount() == 0) + { + // In this case, we leave it to the IRegionReadyModule to enable logins + + // LoginLock can currently only be set by a region module implementation. + // If somehow this hasn't been done then the quickest way to bugfix is to see the + // NullReferenceException + IRegionReadyModule rrm = RequestModuleInterface(); + rrm.TriggerRegionReady(this); + } + } + } } catch (Exception e) { - m_log.WarnFormat( - "[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}", e.Message, e.StackTrace); + m_log.ErrorFormat( + "[SCENE]: Failed on region {0} with exception {1}{2}", + RegionInfo.RegionName, e.Message, e.StackTrace); } - } - /// - /// Register this region with a grid service - /// - /// Thrown if registration of the region itself fails. - public void RegisterRegionWithGrid() - { - m_sceneGridService.SetScene(this); + EventManager.TriggerRegionHeartbeatEnd(this); + otherMS = eventMS + backupMS + terrainMS + landMS; - //// Unfortunately this needs to be here and it can't be async. - //// The map tile image is stored in RegionSettings, but it also needs to be - //// stored in the GridService, because that's what the world map module uses - //// to send the map image UUIDs (of other regions) to the viewer... - if (m_generateMaptiles) - RegenerateMaptile(); - - GridRegion region = new GridRegion(RegionInfo); - string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); -// m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>", -// m_regionName, -// RegionInfo.RegionID, -// RegionInfo.RegionLocX, RegionInfo.RegionLocY, -// RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); - - if (error != String.Empty) - throw new Exception(error); - } - - #endregion - - #region Load Land - - /// - /// Loads all Parcel data from the datastore for region identified by regionID - /// - /// Unique Identifier of the Region to load parcel data for - public void loadAllLandObjectsFromStorage(UUID regionID) - { - m_log.Info("[SCENE]: Loading land objects from storage"); - List landData = SimulationDataService.LoadLandObjects(regionID); - - if (LandChannel != null) - { - if (landData.Count == 0) - { - EventManager.TriggerNoticeNoLandDataFromStorage(); - } - else - { - EventManager.TriggerIncomingLandDataFromStorage(landData); - } - } - else + // Get the elapsed time for the simulation frame + simFrameStopwatch.Stop(); + preciseSimFrameTime += + simFrameStopwatch.Elapsed.TotalMilliseconds; + + if (!UpdateOnTimer) { - m_log.Error("[SCENE]: Land Channel is not defined. Cannot load from storage!"); - } - } + Watchdog.UpdateThread(); - #endregion + spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick); - #region Primitives Methods - - /// - /// Loads the World's objects - /// - /// - public virtual void LoadPrimsFromStorage(UUID regionID) - { - LoadingPrims = true; - m_log.Info("[SCENE]: Loading objects from datastore"); - - List PrimsFromDB = SimulationDataService.LoadObjects(regionID); - - m_log.InfoFormat("[SCENE]: Loaded {0} objects from the datastore", PrimsFromDB.Count); - - foreach (SceneObjectGroup group in PrimsFromDB) - { - AddRestoredSceneObject(group, true, true); - EventManager.TriggerOnSceneObjectLoaded(group); - SceneObjectPart rootPart = group.GetPart(group.UUID); - rootPart.Flags &= ~PrimFlags.Scripted; - rootPart.TrimPermissions(); - - // Don't do this here - it will get done later on when sculpt data is loaded. -// group.CheckSculptAndLoad(); - } - - LoadingPrims = false; - EventManager.TriggerPrimsLoaded(this); - } - - public bool SupportsRayCastFiltered() - { - if (PhysicsScene == null) - return false; - return PhysicsScene.SupportsRaycastWorldFiltered(); - } - - public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) - { - if (PhysicsScene == null) - return null; - return PhysicsScene.RaycastWorld(position, direction, length, Count,filter); - } - - /// - /// Gets a new rez location based on the raycast and the size of the object that is being rezzed. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) - { - Vector3 pos = Vector3.Zero; - if (RayEndIsIntersection == (byte)1) - { - pos = RayEnd; - return pos; - } - - if (RayTargetID != UUID.Zero) - { - SceneObjectPart target = GetSceneObjectPart(RayTargetID); - - Vector3 direction = Vector3.Normalize(RayEnd - RayStart); - Vector3 AXOrigin = RayStart; - Vector3 AXdirection = direction; - - if (target != null) - { - pos = target.AbsolutePosition; - //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); - - // TODO: Raytrace better here - - //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); - Ray NewRay = new Ray(AXOrigin, AXdirection); - - // Ray Trace against target here - EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); - - // Un-comment out the following line to Get Raytrace results printed to the console. - // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); - float ScaleOffset = 0.5f; - - // If we hit something - if (ei.HitTF) - { - Vector3 scaleComponent = ei.AAfaceNormal; - if (scaleComponent.X != 0) ScaleOffset = scale.X; - if (scaleComponent.Y != 0) ScaleOffset = scale.Y; - if (scaleComponent.Z != 0) ScaleOffset = scale.Z; - ScaleOffset = Math.Abs(ScaleOffset); - Vector3 intersectionpoint = ei.ipoint; - Vector3 normal = ei.normal; - // Set the position to the intersection point - Vector3 offset = (normal * (ScaleOffset / 2f)); - pos = (intersectionpoint + offset); - - //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f - //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method - // Un-offset the prim (it gets offset later by the consumer method) - //pos.Z -= 0.25F; - - } - - return pos; - } - else - { - // We don't have a target here, so we're going to raytrace all the objects in the scene. - - EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); - - // Un-comment the following line to print the raytrace results to the console. - //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); - - if (ei.HitTF) - { - pos = ei.ipoint; - } - else - { - // fall back to our stupid functionality - pos = RayEnd; - } - - return pos; - } + if (spareMS > 0) + m_updateWaitEvent.WaitOne(spareMS); + else + spareMS = 0; } else { - // fall back to our stupid functionality - pos = RayEnd; - - //increase height so its above the ground. - //should be getting the normal of the ground at the rez point and using that? - pos.Z += scale.Z / 2f; - return pos; + spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); } - } + // Get the total frame time + totalFrameStopwatch.Stop(); + preciseTotalFrameTime = + totalFrameStopwatch.Elapsed.TotalMilliseconds; - /// - /// Create a New SceneObjectGroup/Part by raycasting - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public virtual void AddNewPrim(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape, - byte bypassRaycast, Vector3 RayStart, UUID RayTargetID, - byte RayEndIsIntersection) - { - Vector3 pos = GetNewRezLocation(RayStart, RayEnd, RayTargetID, rot, bypassRaycast, RayEndIsIntersection, true, new Vector3(0.5f, 0.5f, 0.5f), false); + // Restart the stopwatch for the total time of the next frame + totalFrameStopwatch.Restart(); - if (Permissions.CanRezObject(1, ownerID, pos)) - { - // rez ON the ground, not IN the ground - // pos.Z += 0.25F; The rez point should now be correct so that its not in the ground + previousFrameTick = m_lastFrameTick; + frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); + m_lastFrameTick = Util.EnvironmentTickCount(); - AddNewPrim(ownerID, groupID, pos, rot, shape); + // if (Frame%m_update_avatars == 0) + // UpdateInWorldTime(); + StatsReporter.AddPhysicsFPS(physicsFPS); + StatsReporter.AddTimeDilation(TimeDilation); + StatsReporter.AddFPS(1); + + StatsReporter.addFrameMS(frameMS); + StatsReporter.addAgentMS(agentMS); + StatsReporter.addPhysicsMS(physicsMS + physicsMS2); + StatsReporter.addOtherMS(otherMS); + StatsReporter.AddSpareMS(spareMS); + StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); + + // Send the correct time values to the stats reporter for the + // frame times + StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime, + preciseSimFrameTime, precisePhysicsFrameTime, 0.0); + + // Send the correct number of frames that the physics library + // has processed to the stats reporter + StatsReporter.addPhysicsFrame(1); + + // Optionally warn if a frame takes double the amount of time that it should. + if (DebugUpdates + && Util.EnvironmentTickCountSubtract( + m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2) + m_log.WarnFormat( + "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", + Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), + MinFrameTicks, + RegionInfo.RegionName); + } + + // Finished updating scene frame, so stop the total frame's Stopwatch + totalFrameStopwatch.Stop(); + + return spareMS >= 0; + } + + public void AddGroupTarget(SceneObjectGroup grp) + { + lock (m_groupsWithTargets) + m_groupsWithTargets[grp.UUID] = grp; + } + + public void RemoveGroupTarget(SceneObjectGroup grp) + { + lock (m_groupsWithTargets) + m_groupsWithTargets.Remove(grp.UUID); + } + + private void CheckAtTargets() + { + List objs = null; + + lock (m_groupsWithTargets) + { + if (m_groupsWithTargets.Count != 0) + objs = new List(m_groupsWithTargets.Values); + } + + if (objs != null) + { + foreach (SceneObjectGroup entry in objs) + entry.checkAtTargets(); + } + } + + /// + /// Send out simstats data to all clients + /// + /// Stats on the Simulator's performance + private void SendSimStatsPackets(SimStats stats) + { + ForEachRootClient(delegate(IClientAPI client) + { + client.SendSimStats(stats); + }); + } + + /// + /// Update the terrain if it needs to be updated. + /// + private void UpdateTerrain() + { + EventManager.TriggerTerrainTick(); + } + + /// + /// Back up queued up changes + /// + private void UpdateStorageBackup() + { + if (!m_backingup) + { + m_backingup = true; + WorkManager.RunInThread(o => Backup(false), null, string.Format("BackupWaitCallback ({0})", Name)); + } + } + + /// + /// Sends out the OnFrame event to the modules + /// + private void UpdateEvents() + { + m_eventManager.TriggerOnFrame(); + } + + /// + /// Backup the scene. + /// + /// + /// This acts as the main method of the backup thread. In a regression test whether the backup thread is not + /// running independently this can be invoked directly. + /// + /// + /// If true, then any changes that have not yet been persisted are persisted. If false, + /// then the persistence decision is left to the backup code (in some situations, such as object persistence, + /// it's much more efficient to backup multiple changes at once rather than every single one). + /// + public void Backup(bool forced) + { + lock (m_returns) + { + EventManager.TriggerOnBackup(SimulationDataService, forced); + m_backingup = false; + + foreach (KeyValuePair ret in m_returns) + { + UUID transaction = UUID.Random(); + + GridInstantMessage msg = new GridInstantMessage(); + msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server + msg.toAgentID = new Guid(ret.Key.ToString()); + msg.imSessionID = new Guid(transaction.ToString()); + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.fromAgentName = "Server"; + msg.dialog = (byte)19; // Object msg + msg.fromGroup = false; + msg.offline = (byte)0; + msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; + msg.Position = Vector3.Zero; + msg.RegionID = RegionInfo.RegionID.Guid; + + // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3. + msg.binaryBucket = Util.StringToBytes256("\0"); + if (ret.Value.count > 1) + msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); + else + msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); + + IMessageTransferModule tr = RequestModuleInterface(); + if (tr != null) + tr.SendInstantMessage(msg, delegate(bool success) { }); + } + m_returns.Clear(); + } + } + + /// + /// Synchronous force backup. For deletes and links/unlinks + /// + /// Object to be backed up + public void ForceSceneObjectBackup(SceneObjectGroup group) + { + if (group != null) + { + group.HasGroupChanged = true; + group.ProcessBackup(SimulationDataService, true); + } + } + + /// + /// Tell an agent that their object has been returned. + /// + /// + /// The actual return is handled by the caller. + /// + /// Avatar Unique Id + /// Name of object returned + /// Location of object returned + /// Reasion for object return + public void AddReturn(UUID agentID, string objectName, Vector3 location, string reason) + { + lock (m_returns) + { + if (m_returns.ContainsKey(agentID)) + { + ReturnInfo info = m_returns[agentID]; + info.count++; + m_returns[agentID] = info; } else { - IClientAPI client = null; - if (TryGetClient(ownerID, out client)) - client.SendAlertMessage("You cannot create objects here."); - } - } - - public virtual SceneObjectGroup AddNewPrim( - UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) - { - //m_log.DebugFormat( - // "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName); - - SceneObjectGroup sceneObject = null; - - // If an entity creator has been registered for this prim type then use that - if (m_entityCreators.ContainsKey((PCode)shape.PCode)) - { - sceneObject = m_entityCreators[(PCode)shape.PCode].CreateEntity(ownerID, groupID, pos, rot, shape); + ReturnInfo info = new ReturnInfo(); + info.count = 1; + info.objectName = objectName; + info.location = location; + info.reason = reason; + m_returns[agentID] = info; + } + } + } + + #endregion + + #region Load Terrain + + /// + /// Store the terrain in the persistant data store + /// + public void SaveTerrain() + { + SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); + } + + public void StoreWindlightProfile(RegionLightShareData wl) + { + RegionInfo.WindlightSettings = wl; + SimulationDataService.StoreRegionWindlightSettings(wl); + m_eventManager.TriggerOnSaveNewWindlightProfile(); + } + + public void LoadWindlightProfile() + { + RegionInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(RegionInfo.RegionID); + m_eventManager.TriggerOnSaveNewWindlightProfile(); + } + + /// + /// Loads the World heightmap + /// + public override void LoadWorldMap() + { + try + { + TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); + if (map == null) + { + // This should be in the Terrain module, but it isn't because + // the heightmap is needed _way_ before the modules are initialized... + IConfig terrainConfig = m_config.Configs["Terrain"]; + String m_InitialTerrain = "pinhead-island"; + if (terrainConfig != null) + m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); + + m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); + Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); + + SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); } else { - // Otherwise, use this default creation code; - sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - AddNewSceneObject(sceneObject, true); - sceneObject.SetGroup(groupID, null); - } - - if (UserManagementModule != null) - sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID); - - sceneObject.ScheduleGroupForFullUpdate(); - - return sceneObject; - } - - /// - /// Add an object into the scene that has come from storage - /// - /// - /// - /// - /// If true, changes to the object will be reflected in its persisted data - /// If false, the persisted data will not be changed even if the object in the scene is changed - /// - /// - /// If true, we won't persist this object until it changes - /// If false, we'll persist this object immediately - /// - /// - /// If true, we send updates to the client to tell it about this object - /// If false, we leave it up to the caller to do this - /// - /// - /// true if the object was added, false if an object with the same uuid was already in the scene - /// - public bool AddRestoredSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) - { - if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) - { - EventManager.TriggerObjectAddedToScene(sceneObject); - return true; - } + Heightmap = new TerrainChannel(map); + } + } + catch (IOException e) + { + m_log.WarnFormat( + "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}", + e.Message, e.StackTrace); + + // Non standard region size. If there's an old terrain in the database, it might read past the buffer +#pragma warning disable 0162 + if ((int)Constants.RegionSize != 256) + { + Heightmap = new TerrainChannel(); + + SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); + } + } + catch (Exception e) + { + m_log.WarnFormat( + "[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}", e.Message, e.StackTrace); + } + } + + /// + /// Register this region with a grid service + /// + /// Thrown if registration of the region itself fails. + public void RegisterRegionWithGrid() + { + m_sceneGridService.SetScene(this); + + //// Unfortunately this needs to be here and it can't be async. + //// The map tile image is stored in RegionSettings, but it also needs to be + //// stored in the GridService, because that's what the world map module uses + //// to send the map image UUIDs (of other regions) to the viewer... + if (m_generateMaptiles) + RegenerateMaptile(); - return false; + GridRegion region = new GridRegion(RegionInfo); + string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); + // m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>", + // m_regionName, + // RegionInfo.RegionID, + // RegionInfo.RegionLocX, RegionInfo.RegionLocY, + // RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); - } - - /// - /// Add an object into the scene that has come from storage - /// - /// - /// - /// - /// If true, changes to the object will be reflected in its persisted data - /// If false, the persisted data will not be changed even if the object in the scene is changed - /// - /// - /// If true, we won't persist this object until it changes - /// If false, we'll persist this object immediately - /// - /// - /// true if the object was added, false if an object with the same uuid was already in the scene - /// - public bool AddRestoredSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) - { - return AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); - } - - /// - /// Add a newly created object to the scene. Updates are also sent to viewers. - /// - /// - /// - /// If true, the object is made persistent into the scene. - /// If false, the object will not persist over server restarts - /// - /// true if the object was added. false if not - public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) - { - return AddNewSceneObject(sceneObject, attachToBackup, true); - } - - /// - /// Add a newly created object to the scene - /// - /// - /// - /// If true, the object is made persistent into the scene. - /// If false, the object will not persist over server restarts - /// - /// - /// If true, updates for the new scene object are sent to all viewers in range. - /// If false, it is left to the caller to schedule the update - /// - /// true if the object was added. false if not - public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) - { - if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates)) - { - EventManager.TriggerObjectAddedToScene(sceneObject); - return true; - } - - return false; - } - - /// - /// Add a newly created object to the scene. - /// - /// - /// This method does not send updates to the client - callers need to handle this themselves. - /// - /// - /// - /// Position of the object. If null then the position stored in the object is used. - /// Rotation of the object. If null then the rotation stored in the object is used. - /// Velocity of the object. This parameter only has an effect if the object is physical - /// - public bool AddNewSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) - { - if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel)) - { - EventManager.TriggerObjectAddedToScene(sceneObject); - return true; - } + if (error != String.Empty) + throw new Exception(error); + } - return false; - } - - /// - /// Delete every object from the scene. This does not include attachments worn by avatars. - /// - public void DeleteAllSceneObjects() - { - lock (Entities) - { - EntityBase[] entities = Entities.GetEntities(); - foreach (EntityBase e in entities) - { - if (e is SceneObjectGroup) - { - SceneObjectGroup sog = (SceneObjectGroup)e; - if (!sog.IsAttachment) - DeleteSceneObject((SceneObjectGroup)e, false); - } - } - } - } - - /// - /// Synchronously delete the given object from the scene. - /// - /// - /// Scripts are also removed. - /// - /// Object Id - /// Suppress broadcasting changes to other clients. - public void DeleteSceneObject(SceneObjectGroup group, bool silent) - { - DeleteSceneObject(group, silent, true); - } - - /// - /// Synchronously delete the given object from the scene. - /// - /// Object Id - /// Suppress broadcasting changes to other clients. - /// If true, then scripts are removed. If false, then they are only stopped. - public void DeleteSceneObject(SceneObjectGroup group, bool silent, bool removeScripts) - { -// m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); - - if (removeScripts) - group.RemoveScriptInstances(true); - else - group.StopScriptInstances(); + #endregion - SceneObjectPart[] partList = group.Parts; + #region Load Land - foreach (SceneObjectPart part in partList) - { - if (part.KeyframeMotion != null) - { - part.KeyframeMotion.Delete(); - part.KeyframeMotion = null; - } + /// + /// Loads all Parcel data from the datastore for region identified by regionID + /// + /// Unique Identifier of the Region to load parcel data for + public void loadAllLandObjectsFromStorage(UUID regionID) + { + m_log.Info("[SCENE]: Loading land objects from storage"); + List landData = SimulationDataService.LoadLandObjects(regionID); - if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) - { - PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? - } - else if (part.PhysActor != null) - { - part.RemoveFromPhysics(); - } + if (LandChannel != null) + { + if (landData.Count == 0) + { + EventManager.TriggerNoticeNoLandDataFromStorage(); } - - if (UnlinkSceneObject(group, false)) + else { - EventManager.TriggerObjectBeingRemovedFromScene(group); - EventManager.TriggerParcelPrimCountTainted(); + EventManager.TriggerIncomingLandDataFromStorage(landData); } + } + else + { + m_log.Error("[SCENE]: Land Channel is not defined. Cannot load from storage!"); + } + } - group.DeleteGroupFromScene(silent); + #endregion -// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); - } + #region Primitives Methods - /// - /// Unlink the given object from the scene. Unlike delete, this just removes the record of the object - the - /// object itself is not destroyed. - /// - /// The scene object. - /// If true, only deletes from scene, but keeps the object in the database. - /// true if the object was in the scene, false if it was not - public bool UnlinkSceneObject(SceneObjectGroup so, bool softDelete) - { - if (m_sceneGraph.DeleteSceneObject(so.UUID, softDelete)) - { - if (!softDelete) - { - // If the group contains prims whose SceneGroupID is incorrect then force a - // database update, because RemoveObject() works by searching on the SceneGroupID. - // This is an expensive thing to do so only do it if absolutely necessary. - if (so.GroupContainsForeignPrims) - ForceSceneObjectBackup(so); + /// + /// Loads the World's objects + /// + /// + public virtual void LoadPrimsFromStorage(UUID regionID) + { + LoadingPrims = true; + m_log.Info("[SCENE]: Loading objects from datastore"); - so.DetachFromBackup(); - SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID); - } - - // We need to keep track of this state in case this group is still queued for further backup. - so.IsDeleted = true; + List PrimsFromDB = SimulationDataService.LoadObjects(regionID); - return true; - } + m_log.InfoFormat("[SCENE]: Loaded {0} objects from the datastore", PrimsFromDB.Count); + + foreach (SceneObjectGroup group in PrimsFromDB) + { + AddRestoredSceneObject(group, true, true); + EventManager.TriggerOnSceneObjectLoaded(group); + SceneObjectPart rootPart = group.GetPart(group.UUID); + rootPart.Flags &= ~PrimFlags.Scripted; + rootPart.TrimPermissions(); + + // Don't do this here - it will get done later on when sculpt data is loaded. + // group.CheckSculptAndLoad(); + } + + LoadingPrims = false; + EventManager.TriggerPrimsLoaded(this); + } + public bool SupportsRayCastFiltered() + { + if (PhysicsScene == null) return false; - } - - /// - /// Move the given scene object into a new region depending on which region its absolute position has moved - /// into. - /// - /// - /// the attempted out of region position of the scene object - /// the scene object that we're crossing - public void CrossPrimGroupIntoNewRegion(Vector3 attemptedPosition, SceneObjectGroup grp, bool silent) - { - if (grp == null) - return; - if (grp.IsDeleted) - return; - - if (grp.RootPart.DIE_AT_EDGE) - { - // We remove the object here - try - { - DeleteSceneObject(grp, false); - } - catch (Exception) - { - m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border."); - } - return; - } - - if (grp.RootPart.RETURN_AT_EDGE) - { - // We remove the object here - try - { - List objects = new List(); - objects.Add(grp); - SceneObjectGroup[] objectsArray = objects.ToArray(); - returnObjects(objectsArray, UUID.Zero); - } - catch (Exception) - { - m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border."); - } - return; - } + return PhysicsScene.SupportsRaycastWorldFiltered(); + } - if (EntityTransferModule != null) - EntityTransferModule.Cross(grp, attemptedPosition, silent); - } - - // Simple test to see if a position is in the current region. - // This test is mostly used to see if a region crossing is necessary. - // Assuming the position is relative to the region so anything outside its bounds. - // Return 'true' if position inside region. - public bool PositionIsInCurrentRegion(Vector3 pos) - { - bool ret = false; - int xx = (int)Math.Floor(pos.X); - int yy = (int)Math.Floor(pos.Y); - if (xx < 0 || yy < 0) - return false; - - IRegionCombinerModule regionCombinerModule = RequestModuleInterface(); - if (regionCombinerModule == null) - { - // Regular region. Just check for region size - if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY ) - ret = true; + public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) + { + if (PhysicsScene == null) + return null; + return PhysicsScene.RaycastWorld(position, direction, length, Count, filter); + } + + /// + /// Gets a new rez location based on the raycast and the size of the object that is being rezzed. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) + { + Vector3 pos = Vector3.Zero; + if (RayEndIsIntersection == (byte)1) + { + pos = RayEnd; + return pos; + } + + if (RayTargetID != UUID.Zero) + { + SceneObjectPart target = GetSceneObjectPart(RayTargetID); + + Vector3 direction = Vector3.Normalize(RayEnd - RayStart); + Vector3 AXOrigin = RayStart; + Vector3 AXdirection = direction; + + if (target != null) + { + pos = target.AbsolutePosition; + //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); + + // TODO: Raytrace better here + + //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); + Ray NewRay = new Ray(AXOrigin, AXdirection); + + // Ray Trace against target here + EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); + + // Un-comment out the following line to Get Raytrace results printed to the console. + // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); + float ScaleOffset = 0.5f; + + // If we hit something + if (ei.HitTF) + { + Vector3 scaleComponent = ei.AAfaceNormal; + if (scaleComponent.X != 0) ScaleOffset = scale.X; + if (scaleComponent.Y != 0) ScaleOffset = scale.Y; + if (scaleComponent.Z != 0) ScaleOffset = scale.Z; + ScaleOffset = Math.Abs(ScaleOffset); + Vector3 intersectionpoint = ei.ipoint; + Vector3 normal = ei.normal; + // Set the position to the intersection point + Vector3 offset = (normal * (ScaleOffset / 2f)); + pos = (intersectionpoint + offset); + + //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f + //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method + // Un-offset the prim (it gets offset later by the consumer method) + //pos.Z -= 0.25F; + + } + + return pos; } else { - // We're in a mega-region so see if we are still in that larger region - ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy); - } - - return ret; - - } - - /// - /// Called when objects or attachments cross the border, or teleport, between regions. - /// - /// - /// - public bool IncomingCreateObject(Vector3 newPosition, ISceneObject sog) - { - //m_log.DebugFormat(" >>> IncomingCreateObject(sog) <<< {0} deleted? {1} isAttach? {2}", ((SceneObjectGroup)sog).AbsolutePosition, - // ((SceneObjectGroup)sog).IsDeleted, ((SceneObjectGroup)sog).RootPart.IsAttachment); + // We don't have a target here, so we're going to raytrace all the objects in the scene. + + EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); + + // Un-comment the following line to print the raytrace results to the console. + //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); + + if (ei.HitTF) + { + pos = ei.ipoint; + } + else + { + // fall back to our stupid functionality + pos = RayEnd; + } + + return pos; + } + } + else + { + // fall back to our stupid functionality + pos = RayEnd; + + //increase height so its above the ground. + //should be getting the normal of the ground at the rez point and using that? + pos.Z += scale.Z / 2f; + return pos; + } + } + + + /// + /// Create a New SceneObjectGroup/Part by raycasting + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public virtual void AddNewPrim(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape, + byte bypassRaycast, Vector3 RayStart, UUID RayTargetID, + byte RayEndIsIntersection) + { + Vector3 pos = GetNewRezLocation(RayStart, RayEnd, RayTargetID, rot, bypassRaycast, RayEndIsIntersection, true, new Vector3(0.5f, 0.5f, 0.5f), false); + + if (Permissions.CanRezObject(1, ownerID, pos)) + { + // rez ON the ground, not IN the ground + // pos.Z += 0.25F; The rez point should now be correct so that its not in the ground + + AddNewPrim(ownerID, groupID, pos, rot, shape); + } + else + { + IClientAPI client = null; + if (TryGetClient(ownerID, out client)) + client.SendAlertMessage("You cannot create objects here."); + } + } + + public virtual SceneObjectGroup AddNewPrim( + UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) + { + //m_log.DebugFormat( + // "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName); + + SceneObjectGroup sceneObject = null; + + // If an entity creator has been registered for this prim type then use that + if (m_entityCreators.ContainsKey((PCode)shape.PCode)) + { + sceneObject = m_entityCreators[(PCode)shape.PCode].CreateEntity(ownerID, groupID, pos, rot, shape); + } + else + { + // Otherwise, use this default creation code; + sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); + AddNewSceneObject(sceneObject, true); + sceneObject.SetGroup(groupID, null); + } + + if (UserManagementModule != null) + sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID); + + sceneObject.ScheduleGroupForFullUpdate(); + + return sceneObject; + } + + /// + /// Add an object into the scene that has come from storage + /// + /// + /// + /// + /// If true, changes to the object will be reflected in its persisted data + /// If false, the persisted data will not be changed even if the object in the scene is changed + /// + /// + /// If true, we won't persist this object until it changes + /// If false, we'll persist this object immediately + /// + /// + /// If true, we send updates to the client to tell it about this object + /// If false, we leave it up to the caller to do this + /// + /// + /// true if the object was added, false if an object with the same uuid was already in the scene + /// + public bool AddRestoredSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) + { + if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) + { + EventManager.TriggerObjectAddedToScene(sceneObject); + return true; + } + + return false; + + } + + /// + /// Add an object into the scene that has come from storage + /// + /// + /// + /// + /// If true, changes to the object will be reflected in its persisted data + /// If false, the persisted data will not be changed even if the object in the scene is changed + /// + /// + /// If true, we won't persist this object until it changes + /// If false, we'll persist this object immediately + /// + /// + /// true if the object was added, false if an object with the same uuid was already in the scene + /// + public bool AddRestoredSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) + { + return AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); + } + + /// + /// Add a newly created object to the scene. Updates are also sent to viewers. + /// + /// + /// + /// If true, the object is made persistent into the scene. + /// If false, the object will not persist over server restarts + /// + /// true if the object was added. false if not + public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) + { + return AddNewSceneObject(sceneObject, attachToBackup, true); + } + + /// + /// Add a newly created object to the scene + /// + /// + /// + /// If true, the object is made persistent into the scene. + /// If false, the object will not persist over server restarts + /// + /// + /// If true, updates for the new scene object are sent to all viewers in range. + /// If false, it is left to the caller to schedule the update + /// + /// true if the object was added. false if not + public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) + { + if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates)) + { + EventManager.TriggerObjectAddedToScene(sceneObject); + return true; + } + + return false; + } + + /// + /// Add a newly created object to the scene. + /// + /// + /// This method does not send updates to the client - callers need to handle this themselves. + /// + /// + /// + /// Position of the object. If null then the position stored in the object is used. + /// Rotation of the object. If null then the rotation stored in the object is used. + /// Velocity of the object. This parameter only has an effect if the object is physical + /// + public bool AddNewSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) + { + if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel)) + { + EventManager.TriggerObjectAddedToScene(sceneObject); + return true; + } + + return false; + } + + /// + /// Delete every object from the scene. This does not include attachments worn by avatars. + /// + public void DeleteAllSceneObjects() + { + lock (Entities) + { + EntityBase[] entities = Entities.GetEntities(); + foreach (EntityBase e in entities) + { + if (e is SceneObjectGroup) + { + SceneObjectGroup sog = (SceneObjectGroup)e; + if (!sog.IsAttachment) + DeleteSceneObject((SceneObjectGroup)e, false); + } + } + } + } + + /// + /// Synchronously delete the given object from the scene. + /// + /// + /// Scripts are also removed. + /// + /// Object Id + /// Suppress broadcasting changes to other clients. + public void DeleteSceneObject(SceneObjectGroup group, bool silent) + { + DeleteSceneObject(group, silent, true); + } + + /// + /// Synchronously delete the given object from the scene. + /// + /// Object Id + /// Suppress broadcasting changes to other clients. + /// If true, then scripts are removed. If false, then they are only stopped. + public void DeleteSceneObject(SceneObjectGroup group, bool silent, bool removeScripts) + { + // m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); + + if (removeScripts) + group.RemoveScriptInstances(true); + else + group.StopScriptInstances(); + + SceneObjectPart[] partList = group.Parts; + + foreach (SceneObjectPart part in partList) + { + if (part.KeyframeMotion != null) + { + part.KeyframeMotion.Delete(); + part.KeyframeMotion = null; + } + + if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) + { + PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? + } + else if (part.PhysActor != null) + { + part.RemoveFromPhysics(); + } + } + + if (UnlinkSceneObject(group, false)) + { + EventManager.TriggerObjectBeingRemovedFromScene(group); + EventManager.TriggerParcelPrimCountTainted(); + } + + group.DeleteGroupFromScene(silent); + + // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); + } + + /// + /// Unlink the given object from the scene. Unlike delete, this just removes the record of the object - the + /// object itself is not destroyed. + /// + /// The scene object. + /// If true, only deletes from scene, but keeps the object in the database. + /// true if the object was in the scene, false if it was not + public bool UnlinkSceneObject(SceneObjectGroup so, bool softDelete) + { + if (m_sceneGraph.DeleteSceneObject(so.UUID, softDelete)) + { + if (!softDelete) + { + // If the group contains prims whose SceneGroupID is incorrect then force a + // database update, because RemoveObject() works by searching on the SceneGroupID. + // This is an expensive thing to do so only do it if absolutely necessary. + if (so.GroupContainsForeignPrims) + ForceSceneObjectBackup(so); + + so.DetachFromBackup(); + SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID); + } + + // We need to keep track of this state in case this group is still queued for further backup. + so.IsDeleted = true; - SceneObjectGroup newObject; + return true; + } + + return false; + } + + /// + /// Move the given scene object into a new region depending on which region its absolute position has moved + /// into. + /// + /// + /// the attempted out of region position of the scene object + /// the scene object that we're crossing + public void CrossPrimGroupIntoNewRegion(Vector3 attemptedPosition, SceneObjectGroup grp, bool silent) + { + if (grp == null) + return; + if (grp.IsDeleted) + return; + + if (grp.RootPart.DIE_AT_EDGE) + { + // We remove the object here try { - newObject = (SceneObjectGroup)sog; + DeleteSceneObject(grp, false); } - catch (Exception e) + catch (Exception) { - m_log.WarnFormat("[INTERREGION]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace); - return false; + m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border."); } + return; + } - if (!EntityTransferModule.HandleIncomingSceneObject(newObject, newPosition)) - return false; - - // Do this as late as possible so that listeners have full access to the incoming object - EventManager.TriggerOnIncomingSceneObject(newObject); - - return true; - } - - /// - /// Adds a Scene Object group to the Scene. - /// Verifies that the creator of the object is not banned from the simulator. - /// Checks if the item is an Attachment - /// - /// - /// True if the SceneObjectGroup was added, False if it was not - public bool AddSceneObject(SceneObjectGroup sceneObject) - { - // Force allocation of new LocalId - // - SceneObjectPart[] parts = sceneObject.Parts; - for (int i = 0; i < parts.Length; i++) - parts[i].LocalId = 0; - - if (sceneObject.IsAttachmentCheckFull()) // Attachment - { - sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); - sceneObject.RootPart.AddFlag(PrimFlags.Phantom); - - // Don't sent a full update here because this will cause full updates to be sent twice for - // attachments on region crossings, resulting in viewer glitches. - AddRestoredSceneObject(sceneObject, false, false, false); - - // Handle attachment special case - SceneObjectPart RootPrim = sceneObject.RootPart; - - // Fix up attachment Parent Local ID - ScenePresence sp = GetScenePresence(sceneObject.OwnerID); - - if (sp != null) - { - SceneObjectGroup grp = sceneObject; - -// m_log.DebugFormat( -// "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID); -// m_log.DebugFormat( -// "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); - - RootPrim.RemFlag(PrimFlags.TemporaryOnRez); - - // We must currently not resume scripts at this stage since AttachmentsModule does not have the - // information that this is due to a teleport/border cross rather than an ordinary attachment. - // We currently do this in Scene.MakeRootAgent() instead. - if (AttachmentsModule != null) - AttachmentsModule.AttachObject(sp, grp, 0, false, false, true); - } - else - { - RootPrim.RemFlag(PrimFlags.TemporaryOnRez); - RootPrim.AddFlag(PrimFlags.TemporaryOnRez); - } + if (grp.RootPart.RETURN_AT_EDGE) + { + // We remove the object here + try + { + List objects = new List(); + objects.Add(grp); + SceneObjectGroup[] objectsArray = objects.ToArray(); + returnObjects(objectsArray, UUID.Zero); } - else + catch (Exception) { - AddRestoredSceneObject(sceneObject, true, false); + m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border."); } + return; + } - return true; - } + if (EntityTransferModule != null) + EntityTransferModule.Cross(grp, attemptedPosition, silent); + } + + // Simple test to see if a position is in the current region. + // This test is mostly used to see if a region crossing is necessary. + // Assuming the position is relative to the region so anything outside its bounds. + // Return 'true' if position inside region. + public bool PositionIsInCurrentRegion(Vector3 pos) + { + bool ret = false; + int xx = (int)Math.Floor(pos.X); + int yy = (int)Math.Floor(pos.Y); + if (xx < 0 || yy < 0) + return false; - #endregion + IRegionCombinerModule regionCombinerModule = RequestModuleInterface(); + if (regionCombinerModule == null) + { + // Regular region. Just check for region size + if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY) + ret = true; + } + else + { + // We're in a mega-region so see if we are still in that larger region + ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy); + } + + return ret; + + } + + /// + /// Called when objects or attachments cross the border, or teleport, between regions. + /// + /// + /// + public bool IncomingCreateObject(Vector3 newPosition, ISceneObject sog) + { + //m_log.DebugFormat(" >>> IncomingCreateObject(sog) <<< {0} deleted? {1} isAttach? {2}", ((SceneObjectGroup)sog).AbsolutePosition, + // ((SceneObjectGroup)sog).IsDeleted, ((SceneObjectGroup)sog).RootPart.IsAttachment); + + SceneObjectGroup newObject; + try + { + newObject = (SceneObjectGroup)sog; + } + catch (Exception e) + { + m_log.WarnFormat("[INTERREGION]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace); + return false; + } - #region Add/Remove Avatar Methods + if (!EntityTransferModule.HandleIncomingSceneObject(newObject, newPosition)) + return false; - public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) - { - ScenePresence sp; - bool vialogin; - bool reallyNew = true; + // Do this as late as possible so that listeners have full access to the incoming object + EventManager.TriggerOnIncomingSceneObject(newObject); + + return true; + } + + /// + /// Adds a Scene Object group to the Scene. + /// Verifies that the creator of the object is not banned from the simulator. + /// Checks if the item is an Attachment + /// + /// + /// True if the SceneObjectGroup was added, False if it was not + public bool AddSceneObject(SceneObjectGroup sceneObject) + { + // Force allocation of new LocalId + // + SceneObjectPart[] parts = sceneObject.Parts; + for (int i = 0; i < parts.Length; i++) + parts[i].LocalId = 0; + + if (sceneObject.IsAttachmentCheckFull()) // Attachment + { + sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); + sceneObject.RootPart.AddFlag(PrimFlags.Phantom); + + // Don't sent a full update here because this will cause full updates to be sent twice for + // attachments on region crossings, resulting in viewer glitches. + AddRestoredSceneObject(sceneObject, false, false, false); + + // Handle attachment special case + SceneObjectPart RootPrim = sceneObject.RootPart; + + // Fix up attachment Parent Local ID + ScenePresence sp = GetScenePresence(sceneObject.OwnerID); - // Update the number of users attempting to login - StatsReporter.UpdateUsersLoggingIn(true); + if (sp != null) + { + SceneObjectGroup grp = sceneObject; - // Validation occurs in LLUDPServer - // - // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with - // each other. In practice, this does not currently occur in the code. - AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); + // m_log.DebugFormat( + // "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID); + // m_log.DebugFormat( + // "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); - // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection - // and a simultaneous one that removes it (as can happen if the client is closed at a particular point - // whilst connecting). - // - // It would be easier to lock across all NewUserConnection(), AddNewAgent() and - // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service - // response in some module listening to AddNewAgent()) from holding up unrelated agent calls. - // - // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all - // AddNewClient() operations (though not other ops). - // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. - lock (aCircuit) - { - vialogin - = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 - || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; - - // CheckHeartbeat(); - - sp = GetScenePresence(client.AgentId); - - // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this - // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause - // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already - // connected. - if (sp == null) - { - m_log.DebugFormat( - "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", - client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); - - sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); - - // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the - // client is for a root or child agent. - // We must also set this before adding the client to the client manager so that an exception later on - // does not leave a client manager entry without the scene agent set, which will cause other code - // to fail since any entry in the client manager should have a ScenePresence - // - // XXX: This may be better set for a new client before that client is added to the client manager. - // But need to know what happens in the case where a ScenePresence is already present (and if this - // actually occurs). - client.SceneAgent = sp; - - m_clientManager.Add(client); - SubscribeToClientEvents(client); - m_eventManager.TriggerOnNewPresence(sp); - - sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; - } - else - { - // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the - // client is for a root or child agent. - // XXX: This may be better set for a new client before that client is added to the client manager. - // But need to know what happens in the case where a ScenePresence is already present (and if this - // actually occurs). - client.SceneAgent = sp; - - m_log.WarnFormat( - "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", - sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); - - reallyNew = false; - } - - // This is currently also being done earlier in NewUserConnection for real users to see if this - // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other - // places. However, we still need to do it here for NPCs. - CacheUserName(sp, aCircuit); - - if (reallyNew) - EventManager.TriggerOnNewClient(client); - - if (vialogin) - EventManager.TriggerOnClientLogin(client); - } - - // User has logged into the scene so update the list of users logging - // in - StatsReporter.UpdateUsersLoggingIn(false); - - m_LastLogin = Util.EnvironmentTickCount(); - - return sp; - } - - /// - /// Returns the Home URI of the agent, or null if unknown. - /// - public string GetAgentHomeURI(UUID agentID) - { - AgentCircuitData circuit = AuthenticateHandler.GetAgentCircuitData(agentID); - if (circuit != null && circuit.ServiceURLs != null && circuit.ServiceURLs.ContainsKey("HomeURI")) - return circuit.ServiceURLs["HomeURI"].ToString(); - else - return null; - } - - /// - /// Cache the user name for later use. - /// - /// - /// - private void CacheUserName(ScenePresence sp, AgentCircuitData aCircuit) - { - if (UserManagementModule != null) - { - string first = aCircuit.firstname, last = aCircuit.lastname; - - if (sp != null && sp.PresenceType == PresenceType.Npc) - { - UserManagementModule.AddUser(aCircuit.AgentID, first, last); - } - else - { - string homeURL = string.Empty; - - if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) - homeURL = aCircuit.ServiceURLs["HomeURI"].ToString(); - - if (aCircuit.lastname.StartsWith("@")) - { - string[] parts = aCircuit.firstname.Split('.'); - if (parts.Length >= 2) - { - first = parts[0]; - last = parts[1]; - } - } - - UserManagementModule.AddUser(aCircuit.AgentID, first, last, homeURL); - } - } - } - - private bool VerifyClient(AgentCircuitData aCircuit, System.Net.IPEndPoint ep, out bool vialogin) - { - vialogin = false; - - // Do the verification here - if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) - { - m_log.DebugFormat("[SCENE]: Incoming client {0} {1} in region {2} via HG login", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); - vialogin = true; - IUserAgentVerificationModule userVerification = RequestModuleInterface(); - if (userVerification != null && ep != null) - { - if (!userVerification.VerifyClient(aCircuit, ep.Address.ToString())) - { - // uh-oh, this is fishy - m_log.DebugFormat("[SCENE]: User Client Verification for {0} {1} in {2} returned false", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); - return false; - } - else - m_log.DebugFormat("[SCENE]: User Client Verification for {0} {1} in {2} returned true", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + RootPrim.RemFlag(PrimFlags.TemporaryOnRez); - } + // We must currently not resume scripts at this stage since AttachmentsModule does not have the + // information that this is due to a teleport/border cross rather than an ordinary attachment. + // We currently do this in Scene.MakeRootAgent() instead. + if (AttachmentsModule != null) + AttachmentsModule.AttachObject(sp, grp, 0, false, false, true); } - - else if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0) + else + { + RootPrim.RemFlag(PrimFlags.TemporaryOnRez); + RootPrim.AddFlag(PrimFlags.TemporaryOnRez); + } + } + else + { + AddRestoredSceneObject(sceneObject, true, false); + } + + return true; + } + + #endregion + + #region Add/Remove Avatar Methods + + public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) + { + ScenePresence sp; + bool vialogin; + bool reallyNew = true; + + // Update the number of users attempting to login + StatsReporter.UpdateUsersLoggingIn(true); + + // Validation occurs in LLUDPServer + // + // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with + // each other. In practice, this does not currently occur in the code. + AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); + + // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection + // and a simultaneous one that removes it (as can happen if the client is closed at a particular point + // whilst connecting). + // + // It would be easier to lock across all NewUserConnection(), AddNewAgent() and + // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service + // response in some module listening to AddNewAgent()) from holding up unrelated agent calls. + // + // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all + // AddNewClient() operations (though not other ops). + // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. + lock (aCircuit) + { + vialogin + = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 + || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; + + // CheckHeartbeat(); + + sp = GetScenePresence(client.AgentId); + + // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this + // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause + // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already + // connected. + if (sp == null) { - m_log.DebugFormat("[SCENE]: Incoming client {0} {1} in region {2} via regular login. Client IP verification not performed.", - aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); - vialogin = true; + m_log.DebugFormat( + "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", + client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); + + sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); + + // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the + // client is for a root or child agent. + // We must also set this before adding the client to the client manager so that an exception later on + // does not leave a client manager entry without the scene agent set, which will cause other code + // to fail since any entry in the client manager should have a ScenePresence + // + // XXX: This may be better set for a new client before that client is added to the client manager. + // But need to know what happens in the case where a ScenePresence is already present (and if this + // actually occurs). + client.SceneAgent = sp; + + m_clientManager.Add(client); + SubscribeToClientEvents(client); + m_eventManager.TriggerOnNewPresence(sp); + + sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; } + else + { + // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the + // client is for a root or child agent. + // XXX: This may be better set for a new client before that client is added to the client manager. + // But need to know what happens in the case where a ScenePresence is already present (and if this + // actually occurs). + client.SceneAgent = sp; - return true; - } - - // Called by Caps, on the first HTTP contact from the client - public override bool CheckClient(UUID agentID, System.Net.IPEndPoint ep) - { - AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(agentID); - if (aCircuit != null) - { - bool vialogin = false; - if (!VerifyClient(aCircuit, ep, out vialogin)) - { - // if it doesn't pass, we remove the agentcircuitdata altogether - // and the scene presence and the client, if they exist - try - { - // We need to wait for the client to make UDP contact first. - // It's the UDP contact that creates the scene presence - ScenePresence sp = WaitGetScenePresence(agentID); - if (sp != null) - { - PresenceService.LogoutAgent(sp.ControllingClient.SessionId); - - CloseAgent(sp.UUID, false); - } - else - { - m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID); - } - // BANG! SLASH! - m_authenticateHandler.RemoveCircuit(agentID); + m_log.WarnFormat( + "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", + sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); - return false; - } - catch (Exception e) - { - m_log.DebugFormat("[SCENE]: Exception while closing aborted client: {0}", e.StackTrace); - } - } - else - return true; + reallyNew = false; } - return false; - } - - /// - /// Register for events from the client - /// - /// The IClientAPI of the connected client - public virtual void SubscribeToClientEvents(IClientAPI client) - { - SubscribeToClientTerrainEvents(client); - SubscribeToClientPrimEvents(client); - SubscribeToClientPrimRezEvents(client); - SubscribeToClientInventoryEvents(client); - SubscribeToClientTeleportEvents(client); - SubscribeToClientScriptEvents(client); - SubscribeToClientParcelEvents(client); - SubscribeToClientGridEvents(client); - SubscribeToClientNetworkEvents(client); - } - - public virtual void SubscribeToClientTerrainEvents(IClientAPI client) - { - client.OnRegionHandShakeReply += SendLayerData; - } - - public virtual void SubscribeToClientPrimEvents(IClientAPI client) - { - client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; - client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; - - client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; - client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; - 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 += DeRezObjects; - - client.OnObjectName += m_sceneGraph.PrimName; - client.OnObjectClickAction += m_sceneGraph.PrimClickAction; - client.OnObjectMaterial += m_sceneGraph.PrimMaterial; - client.OnLinkObjects += LinkObjects; - client.OnDelinkObjects += DelinkObjects; - client.OnObjectDuplicate += DuplicateObject; - client.OnObjectDuplicateOnRay += doObjectDuplicateOnRay; - client.OnUpdatePrimFlags += m_sceneGraph.UpdatePrimFlags; - client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily; - client.OnObjectPermissions += HandleObjectPermissionsUpdate; - client.OnGrabObject += ProcessObjectGrab; - client.OnGrabUpdate += ProcessObjectGrabUpdate; - client.OnDeGrabObject += ProcessObjectDeGrab; - client.OnUndo += m_sceneGraph.HandleUndo; - client.OnRedo += m_sceneGraph.HandleRedo; - client.OnObjectDescription += m_sceneGraph.PrimDescription; - client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable; - client.OnObjectOwner += ObjectOwner; - client.OnObjectGroupRequest += HandleObjectGroupUpdate; - } - - public virtual void SubscribeToClientPrimRezEvents(IClientAPI client) - { - client.OnAddPrim += AddNewPrim; - client.OnRezObject += RezObject; - } - - public virtual void SubscribeToClientInventoryEvents(IClientAPI client) - { - client.OnLinkInventoryItem += HandleLinkInventoryItem; - client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; - client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; - client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!! - client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents; - client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!! - client.OnFetchInventory += m_asyncInventorySender.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 SubscribeToClientTeleportEvents(IClientAPI client) - { - client.OnTeleportLocationRequest += RequestTeleportLocation; - } - - public virtual void SubscribeToClientScriptEvents(IClientAPI client) - { - client.OnScriptReset += ProcessScriptReset; - client.OnGetScriptRunning += GetScriptRunning; - client.OnSetScriptRunning += SetScriptRunning; - } - - public virtual void SubscribeToClientParcelEvents(IClientAPI client) - { - client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel; - client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime; - client.OnParcelBuy += ProcessParcelBuy; - } - - public virtual void SubscribeToClientGridEvents(IClientAPI client) - { - //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; - client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; - } - - public virtual void SubscribeToClientNetworkEvents(IClientAPI client) - { - client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; - client.OnViewerEffect += ProcessViewerEffect; - } - - /// - /// Unsubscribe the client from events. - /// - /// FIXME: Not called anywhere! - /// The IClientAPI of the client - public virtual void UnSubscribeToClientEvents(IClientAPI client) - { - UnSubscribeToClientTerrainEvents(client); - UnSubscribeToClientPrimEvents(client); - UnSubscribeToClientPrimRezEvents(client); - UnSubscribeToClientInventoryEvents(client); - UnSubscribeToClientTeleportEvents(client); - UnSubscribeToClientScriptEvents(client); - UnSubscribeToClientParcelEvents(client); - UnSubscribeToClientGridEvents(client); - UnSubscribeToClientNetworkEvents(client); - } - - public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) - { - client.OnRegionHandShakeReply -= SendLayerData; - } - - public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) - { - client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; - client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; - - client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; - client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; - 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 -= DeRezObjects; - client.OnObjectName -= m_sceneGraph.PrimName; - client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; - client.OnObjectMaterial -= m_sceneGraph.PrimMaterial; - client.OnLinkObjects -= LinkObjects; - client.OnDelinkObjects -= DelinkObjects; - client.OnObjectDuplicate -= 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.OnRedo -= m_sceneGraph.HandleRedo; - client.OnObjectDescription -= m_sceneGraph.PrimDescription; - 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.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; - client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; - client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! - client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents; - client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!! - client.OnFetchInventory -= m_asyncInventorySender.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 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.OnParcelReturnObjectsRequest -= LandChannel.ReturnObjectsInParcel; - client.OnParcelSetOtherCleanTime -= LandChannel.SetParcelOtherCleanTime; - client.OnParcelBuy -= ProcessParcelBuy; - } - - public virtual void UnSubscribeToClientGridEvents(IClientAPI client) - { - //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; - client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; - } - - public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) - { - client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats; - client.OnViewerEffect -= ProcessViewerEffect; - } - - /// - /// Teleport an avatar to their home region - /// - /// The avatar's Unique ID - /// The IClientAPI for the client - public virtual bool TeleportClientHome(UUID agentId, IClientAPI client) - { - if (EntityTransferModule != null) + // This is currently also being done earlier in NewUserConnection for real users to see if this + // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other + // places. However, we still need to do it here for NPCs. + CacheUserName(sp, aCircuit); + + if (reallyNew) + EventManager.TriggerOnNewClient(client); + + if (vialogin) + EventManager.TriggerOnClientLogin(client); + } + + // User has logged into the scene so update the list of users logging + // in + StatsReporter.UpdateUsersLoggingIn(false); + + m_LastLogin = Util.EnvironmentTickCount(); + + return sp; + } + + /// + /// Returns the Home URI of the agent, or null if unknown. + /// + public string GetAgentHomeURI(UUID agentID) + { + AgentCircuitData circuit = AuthenticateHandler.GetAgentCircuitData(agentID); + if (circuit != null && circuit.ServiceURLs != null && circuit.ServiceURLs.ContainsKey("HomeURI")) + return circuit.ServiceURLs["HomeURI"].ToString(); + else + return null; + } + + /// + /// Cache the user name for later use. + /// + /// + /// + private void CacheUserName(ScenePresence sp, AgentCircuitData aCircuit) + { + if (UserManagementModule != null) + { + string first = aCircuit.firstname, last = aCircuit.lastname; + + if (sp != null && sp.PresenceType == PresenceType.Npc) { - return EntityTransferModule.TeleportHome(agentId, client); + UserManagementModule.AddUser(aCircuit.AgentID, first, last); } else { - m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); - client.SendTeleportFailed("Unable to perform teleports on this simulator."); + string homeURL = string.Empty; + + if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) + homeURL = aCircuit.ServiceURLs["HomeURI"].ToString(); + + if (aCircuit.lastname.StartsWith("@")) + { + string[] parts = aCircuit.firstname.Split('.'); + if (parts.Length >= 2) + { + first = parts[0]; + last = parts[1]; + } + } + + UserManagementModule.AddUser(aCircuit.AgentID, first, last, homeURL); + } + } + } + + private bool VerifyClient(AgentCircuitData aCircuit, System.Net.IPEndPoint ep, out bool vialogin) + { + vialogin = false; + + // Do the verification here + if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) + { + m_log.DebugFormat("[SCENE]: Incoming client {0} {1} in region {2} via HG login", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + vialogin = true; + IUserAgentVerificationModule userVerification = RequestModuleInterface(); + if (userVerification != null && ep != null) + { + if (!userVerification.VerifyClient(aCircuit, ep.Address.ToString())) + { + // uh-oh, this is fishy + m_log.DebugFormat("[SCENE]: User Client Verification for {0} {1} in {2} returned false", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + return false; + } + else + m_log.DebugFormat("[SCENE]: User Client Verification for {0} {1} in {2} returned true", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + + } + } + + else if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0) + { + m_log.DebugFormat("[SCENE]: Incoming client {0} {1} in region {2} via regular login. Client IP verification not performed.", + aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + vialogin = true; + } + + return true; + } + + // Called by Caps, on the first HTTP contact from the client + public override bool CheckClient(UUID agentID, System.Net.IPEndPoint ep) + { + AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(agentID); + if (aCircuit != null) + { + bool vialogin = false; + if (!VerifyClient(aCircuit, ep, out vialogin)) + { + // if it doesn't pass, we remove the agentcircuitdata altogether + // and the scene presence and the client, if they exist + try + { + // We need to wait for the client to make UDP contact first. + // It's the UDP contact that creates the scene presence + ScenePresence sp = WaitGetScenePresence(agentID); + if (sp != null) + { + PresenceService.LogoutAgent(sp.ControllingClient.SessionId); + + CloseAgent(sp.UUID, false); + } + else + { + m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID); + } + // BANG! SLASH! + m_authenticateHandler.RemoveCircuit(agentID); + + return false; + } + catch (Exception e) + { + m_log.DebugFormat("[SCENE]: Exception while closing aborted client: {0}", e.StackTrace); + } } - return false; - } - - /// - /// Duplicates object specified by localID. This is the event handler for IClientAPI. - /// - /// ID of object to duplicate - /// - /// - /// Agent doing the duplication - /// Group of new object - public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID) - { - SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Identity); - if (copy != null) - EventManager.TriggerObjectAddedToScene(copy); - } - - /// - /// Duplicates object specified by localID at position raycasted against RayTargetObject using - /// RayEnd and RayStart to determine what the angle of the ray is - /// - /// ID of object to duplicate - /// - /// Agent doing the duplication - /// Group of new object - /// The target of the Ray - /// The ending of the ray (farthest away point) - /// The Beginning of the ray (closest point) - /// Bool to bypass raycasting - /// The End specified is the place to add the object - /// Position the object at the center of the face that it's colliding with - /// Rotate the object the same as the localID object - public void doObjectDuplicateOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, - UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart, - bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) - { - Vector3 pos; - const bool frontFacesOnly = true; - //m_log.Info("HITTARGET: " + RayTargetObj.ToString() + ", COPYTARGET: " + localID.ToString()); - SceneObjectPart target = GetSceneObjectPart(localID); - SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj); - - if (target != null && target2 != null) - { - Vector3 direction = Vector3.Normalize(RayEnd - RayStart); - Vector3 AXOrigin = RayStart; - Vector3 AXdirection = direction; - - pos = target2.AbsolutePosition; - //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); - - // TODO: Raytrace better here - - //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); - Ray NewRay = new Ray(AXOrigin, AXdirection); - - // Ray Trace against target here - EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters); - - // Un-comment out the following line to Get Raytrace results printed to the console. - //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); - float ScaleOffset = 0.5f; - - // If we hit something - if (ei.HitTF) - { - Vector3 scale = target.Scale; - Vector3 scaleComponent = ei.AAfaceNormal; - if (scaleComponent.X != 0) ScaleOffset = scale.X; - if (scaleComponent.Y != 0) ScaleOffset = scale.Y; - if (scaleComponent.Z != 0) ScaleOffset = scale.Z; - ScaleOffset = Math.Abs(ScaleOffset); - Vector3 intersectionpoint = ei.ipoint; - Vector3 normal = ei.normal; - Vector3 offset = normal * (ScaleOffset / 2f); - pos = intersectionpoint + offset; - - // stick in offset format from the original prim - pos = pos - target.ParentGroup.AbsolutePosition; - SceneObjectGroup copy; - if (CopyRotates) - { - Quaternion worldRot = target2.GetWorldRotation(); - - // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); - copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); - //obj.Rotation = worldRot; - //obj.UpdateGroupRotationR(worldRot); - } - else - { - copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); - } - - if (copy != null) - EventManager.TriggerObjectAddedToScene(copy); - } - } - } - - /// - /// Get the avatar apperance for the given client. - /// - /// - /// - public void GetAvatarAppearance(IClientAPI client, out AvatarAppearance appearance) - { - AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); - - if (aCircuit == null) - { - m_log.DebugFormat("[APPEARANCE] Client did not supply a circuit. Non-Linden? Creating default appearance."); - appearance = new AvatarAppearance(); - return; - } - - appearance = aCircuit.Appearance; - if (appearance == null) - { - m_log.DebugFormat("[APPEARANCE]: Appearance not found in {0}, returning default", RegionInfo.RegionName); - appearance = new AvatarAppearance(); - } - } - - /// - /// Remove the given client from the scene. - /// - /// - /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead - /// to properly operate the state machine and avoid race conditions with other close requests (such as directly - /// from viewers). - /// - /// ID of agent to close - /// - /// Close the neighbour child agents associated with this client. - /// - public void RemoveClient(UUID agentID, bool closeChildAgents) - { - AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); + else + return true; + } + + return false; + } + + /// + /// Register for events from the client + /// + /// The IClientAPI of the connected client + public virtual void SubscribeToClientEvents(IClientAPI client) + { + SubscribeToClientTerrainEvents(client); + SubscribeToClientPrimEvents(client); + SubscribeToClientPrimRezEvents(client); + SubscribeToClientInventoryEvents(client); + SubscribeToClientTeleportEvents(client); + SubscribeToClientScriptEvents(client); + SubscribeToClientParcelEvents(client); + SubscribeToClientGridEvents(client); + SubscribeToClientNetworkEvents(client); + } + + public virtual void SubscribeToClientTerrainEvents(IClientAPI client) + { + client.OnRegionHandShakeReply += SendLayerData; + } + + public virtual void SubscribeToClientPrimEvents(IClientAPI client) + { + client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; + client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; + + client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; + client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; + 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 += DeRezObjects; + + client.OnObjectName += m_sceneGraph.PrimName; + client.OnObjectClickAction += m_sceneGraph.PrimClickAction; + client.OnObjectMaterial += m_sceneGraph.PrimMaterial; + client.OnLinkObjects += LinkObjects; + client.OnDelinkObjects += DelinkObjects; + client.OnObjectDuplicate += DuplicateObject; + client.OnObjectDuplicateOnRay += doObjectDuplicateOnRay; + client.OnUpdatePrimFlags += m_sceneGraph.UpdatePrimFlags; + client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily; + client.OnObjectPermissions += HandleObjectPermissionsUpdate; + client.OnGrabObject += ProcessObjectGrab; + client.OnGrabUpdate += ProcessObjectGrabUpdate; + client.OnDeGrabObject += ProcessObjectDeGrab; + client.OnUndo += m_sceneGraph.HandleUndo; + client.OnRedo += m_sceneGraph.HandleRedo; + client.OnObjectDescription += m_sceneGraph.PrimDescription; + client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable; + client.OnObjectOwner += ObjectOwner; + client.OnObjectGroupRequest += HandleObjectGroupUpdate; + } + + public virtual void SubscribeToClientPrimRezEvents(IClientAPI client) + { + client.OnAddPrim += AddNewPrim; + client.OnRezObject += RezObject; + } + + public virtual void SubscribeToClientInventoryEvents(IClientAPI client) + { + client.OnLinkInventoryItem += HandleLinkInventoryItem; + client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; + client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; + client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!! + client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents; + client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!! + client.OnFetchInventory += m_asyncInventorySender.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 SubscribeToClientTeleportEvents(IClientAPI client) + { + client.OnTeleportLocationRequest += RequestTeleportLocation; + } + + public virtual void SubscribeToClientScriptEvents(IClientAPI client) + { + client.OnScriptReset += ProcessScriptReset; + client.OnGetScriptRunning += GetScriptRunning; + client.OnSetScriptRunning += SetScriptRunning; + } + + public virtual void SubscribeToClientParcelEvents(IClientAPI client) + { + client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel; + client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime; + client.OnParcelBuy += ProcessParcelBuy; + } + + public virtual void SubscribeToClientGridEvents(IClientAPI client) + { + //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; + client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; + } + + public virtual void SubscribeToClientNetworkEvents(IClientAPI client) + { + client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; + client.OnViewerEffect += ProcessViewerEffect; + } + + /// + /// Unsubscribe the client from events. + /// + /// FIXME: Not called anywhere! + /// The IClientAPI of the client + public virtual void UnSubscribeToClientEvents(IClientAPI client) + { + UnSubscribeToClientTerrainEvents(client); + UnSubscribeToClientPrimEvents(client); + UnSubscribeToClientPrimRezEvents(client); + UnSubscribeToClientInventoryEvents(client); + UnSubscribeToClientTeleportEvents(client); + UnSubscribeToClientScriptEvents(client); + UnSubscribeToClientParcelEvents(client); + UnSubscribeToClientGridEvents(client); + UnSubscribeToClientNetworkEvents(client); + } + + public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) + { + client.OnRegionHandShakeReply -= SendLayerData; + } + + public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) + { + client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; + client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; + + client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; + client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; + 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 -= DeRezObjects; + client.OnObjectName -= m_sceneGraph.PrimName; + client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; + client.OnObjectMaterial -= m_sceneGraph.PrimMaterial; + client.OnLinkObjects -= LinkObjects; + client.OnDelinkObjects -= DelinkObjects; + client.OnObjectDuplicate -= 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.OnRedo -= m_sceneGraph.HandleRedo; + client.OnObjectDescription -= m_sceneGraph.PrimDescription; + 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.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; + client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; + client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! + client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents; + client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!! + client.OnFetchInventory -= m_asyncInventorySender.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 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.OnParcelReturnObjectsRequest -= LandChannel.ReturnObjectsInParcel; + client.OnParcelSetOtherCleanTime -= LandChannel.SetParcelOtherCleanTime; + client.OnParcelBuy -= ProcessParcelBuy; + } + + public virtual void UnSubscribeToClientGridEvents(IClientAPI client) + { + //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; + client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; + } + + public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) + { + client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats; + client.OnViewerEffect -= ProcessViewerEffect; + } + + /// + /// Teleport an avatar to their home region + /// + /// The avatar's Unique ID + /// The IClientAPI for the client + public virtual bool TeleportClientHome(UUID agentId, IClientAPI client) + { + if (EntityTransferModule != null) + { + return EntityTransferModule.TeleportHome(agentId, client); + } + else + { + m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); + client.SendTeleportFailed("Unable to perform teleports on this simulator."); + } + return false; + } + + /// + /// Duplicates object specified by localID. This is the event handler for IClientAPI. + /// + /// ID of object to duplicate + /// + /// + /// Agent doing the duplication + /// Group of new object + public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID) + { + SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Identity); + if (copy != null) + EventManager.TriggerObjectAddedToScene(copy); + } + + /// + /// Duplicates object specified by localID at position raycasted against RayTargetObject using + /// RayEnd and RayStart to determine what the angle of the ray is + /// + /// ID of object to duplicate + /// + /// Agent doing the duplication + /// Group of new object + /// The target of the Ray + /// The ending of the ray (farthest away point) + /// The Beginning of the ray (closest point) + /// Bool to bypass raycasting + /// The End specified is the place to add the object + /// Position the object at the center of the face that it's colliding with + /// Rotate the object the same as the localID object + public void doObjectDuplicateOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, + UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart, + bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) + { + Vector3 pos; + const bool frontFacesOnly = true; + //m_log.Info("HITTARGET: " + RayTargetObj.ToString() + ", COPYTARGET: " + localID.ToString()); + SceneObjectPart target = GetSceneObjectPart(localID); + SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj); + + if (target != null && target2 != null) + { + Vector3 direction = Vector3.Normalize(RayEnd - RayStart); + Vector3 AXOrigin = RayStart; + Vector3 AXdirection = direction; + + pos = target2.AbsolutePosition; + //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); + + // TODO: Raytrace better here + + //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); + Ray NewRay = new Ray(AXOrigin, AXdirection); + + // Ray Trace against target here + EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters); + + // Un-comment out the following line to Get Raytrace results printed to the console. + //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); + float ScaleOffset = 0.5f; + + // If we hit something + if (ei.HitTF) + { + Vector3 scale = target.Scale; + Vector3 scaleComponent = ei.AAfaceNormal; + if (scaleComponent.X != 0) ScaleOffset = scale.X; + if (scaleComponent.Y != 0) ScaleOffset = scale.Y; + if (scaleComponent.Z != 0) ScaleOffset = scale.Z; + ScaleOffset = Math.Abs(ScaleOffset); + Vector3 intersectionpoint = ei.ipoint; + Vector3 normal = ei.normal; + Vector3 offset = normal * (ScaleOffset / 2f); + pos = intersectionpoint + offset; + + // stick in offset format from the original prim + pos = pos - target.ParentGroup.AbsolutePosition; + SceneObjectGroup copy; + if (CopyRotates) + { + Quaternion worldRot = target2.GetWorldRotation(); + + // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); + copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); + //obj.Rotation = worldRot; + //obj.UpdateGroupRotationR(worldRot); + } + else + { + copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); + } + + if (copy != null) + EventManager.TriggerObjectAddedToScene(copy); + } + } + } + + /// + /// Get the avatar apperance for the given client. + /// + /// + /// + public void GetAvatarAppearance(IClientAPI client, out AvatarAppearance appearance) + { + AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); + + if (aCircuit == null) + { + m_log.DebugFormat("[APPEARANCE] Client did not supply a circuit. Non-Linden? Creating default appearance."); + appearance = new AvatarAppearance(); + return; + } + + appearance = aCircuit.Appearance; + if (appearance == null) + { + m_log.DebugFormat("[APPEARANCE]: Appearance not found in {0}, returning default", RegionInfo.RegionName); + appearance = new AvatarAppearance(); + } + } + + /// + /// Remove the given client from the scene. + /// + /// + /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead + /// to properly operate the state machine and avoid race conditions with other close requests (such as directly + /// from viewers). + /// + /// ID of agent to close + /// + /// Close the neighbour child agents associated with this client. + /// + public void RemoveClient(UUID agentID, bool closeChildAgents) + { + AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); + + // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which + // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not + // However, will keep for now just in case. + if (acd == null) + { + m_log.ErrorFormat( + "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name); + + return; + } + + // TODO: Can we now remove this lock? + lock (acd) + { + bool isChildAgent = false; + + ScenePresence avatar = GetScenePresence(agentID); // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not // However, will keep for now just in case. - if (acd == null) - { - m_log.ErrorFormat( - "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name); - - return; - } - - // TODO: Can we now remove this lock? - lock (acd) - { - bool isChildAgent = false; - - ScenePresence avatar = GetScenePresence(agentID); - - // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which - // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not - // However, will keep for now just in case. - if (avatar == null) - { - m_log.ErrorFormat( - "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); - m_authenticateHandler.RemoveCircuit(agentID); - - return; - } - - try - { - isChildAgent = avatar.IsChildAgent; - - m_log.DebugFormat( - "[SCENE]: Removing {0} agent {1} {2} from {3}", - isChildAgent ? "child" : "root", avatar.Name, agentID, Name); - - // Don't do this to root agents, it's not nice for the viewer - if (closeChildAgents && isChildAgent) - { - // Tell a single agent to disconnect from the region. - // Let's do this via UDP - avatar.ControllingClient.SendShutdownConnectionNotice(); - } - - // Only applies to root agents. - if (avatar.ParentID != 0) - { - avatar.StandUp(); - } - - m_sceneGraph.removeUserCount(!isChildAgent); - - // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop - // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI - if (closeChildAgents && CapsModule != null) - CapsModule.RemoveCaps(agentID); - - if (closeChildAgents && !isChildAgent) - { - List regions = avatar.KnownRegionHandles; - regions.Remove(RegionInfo.RegionHandle); - - // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours. - m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions); - } - - m_eventManager.TriggerClientClosed(agentID, this); - m_eventManager.TriggerOnRemovePresence(agentID); - - if (!isChildAgent) - { - if (AttachmentsModule != null) - { - AttachmentsModule.DeRezAttachments(avatar); - } - - ForEachClient( - delegate(IClientAPI client) - { - //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway - try { client.SendKillObject(new List { avatar.LocalId }); } - catch (NullReferenceException) { } - }); - } - - // It's possible for child agents to have transactions if changes are being made cross-border. - if (AgentTransactionsModule != null) - AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); - } - catch (Exception e) - { - m_log.Error( - string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); - } - finally - { - try - { - // Always clean these structures up so that any failure above doesn't cause them to remain in the - // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering - // the same cleanup exception continually. - m_authenticateHandler.RemoveCircuit(agentID); - m_sceneGraph.RemoveScenePresence(agentID); - m_clientManager.Remove(agentID); - - avatar.Close(); - } - catch (Exception e) - { - m_log.Error( - string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); - } - } - } - - //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); - //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); - } - - /// - /// Removes region from an avatar's known region list. This coincides with child agents. For each child agent, there will be a known region entry. - /// - /// - /// - /// - public void HandleRemoveKnownRegionsFromAvatar(UUID avatarID, List regionslst) - { - ScenePresence av = GetScenePresence(avatarID); - if (av != null) - { - lock (av) - { - for (int i = 0; i < regionslst.Count; i++) - { - av.RemoveNeighbourRegion(regionslst[i]); - } - } - } - } - - #endregion - - #region Entities - - public void SendKillObject(List localIDs) - { - List deleteIDs = new List(); - - foreach (uint localID in localIDs) - { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null) // It is a prim - { - if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid - { - if (part.ParentGroup.RootPart != part) // Child part - continue; - } - } - deleteIDs.Add(localID); - } - - ForEachClient(c => c.SendKillObject(deleteIDs)); - } - - #endregion - - #region RegionComms - - /// - /// Do the work necessary to initiate a new user connection for a particular scene. - /// - /// CircuitData of the agent who is connecting - /// - /// Source region (may be null) - /// Outputs the reason for the false response on this string - /// True if the region accepts this agent. False if it does not. False will - /// also return a reason. - public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason) - { - return NewUserConnection(agent, teleportFlags, source, out reason, true); - } - - /// - /// Do the work necessary to initiate a new user connection for a particular scene. - /// - /// - /// The return bool should allow for connections to be refused, but as not all calling paths - /// take proper notice of it yet, we still allowed banned users in. - /// - /// At the moment this method consists of setting up the caps infrastructure - /// The return bool should allow for connections to be refused, but as not all calling paths - /// take proper notice of it let, we allowed banned users in still. - /// - /// This method is called by the login service (in the case of login) or another simulator (in the case of region - /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection - /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of - /// the LLUDP stack). - /// - /// CircuitData of the agent who is connecting - /// Source region (may be null) - /// Outputs the reason for the false response on this string - /// True for normal presence. False for NPC - /// or other applications where a full grid/Hypergrid presence may not be required. - /// True if the region accepts this agent. False if it does not. False will - /// also return a reason. - public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup) - { - bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || - (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); - bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0); - bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0); - - reason = String.Empty; + if (avatar == null) + { + m_log.ErrorFormat( + "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); + m_authenticateHandler.RemoveCircuit(agentID); - //Teleport flags: - // - // TeleportFlags.ViaGodlikeLure - Border Crossing - // TeleportFlags.ViaLogin - Login - // TeleportFlags.TeleportFlags.ViaLure - Teleport request sent by another user - // TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport + return; + } - // Don't disable this log message - it's too helpful - string curViewer = Util.GetViewerName(acd); - m_log.DebugFormat( - "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9}. {10}", - RegionInfo.RegionName, - (acd.child ? "child" : "root"), - acd.firstname, - acd.lastname, - acd.AgentID, - acd.circuitcode, - acd.IPAddress, - curViewer, - ((TPFlags)teleportFlags).ToString(), - acd.startpos, - (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI) - ); - - if (!LoginsEnabled) - { - reason = "Logins Disabled"; - return false; - } - - //Check if the viewer is banned or in the viewer access list - //We check if the substring is listed for higher flexebility - bool ViewerDenied = true; - - //Check if the specific viewer is listed in the allowed viewer list - if (m_AllowedViewers.Count > 0) - { - foreach (string viewer in m_AllowedViewers) - { - if (viewer == curViewer.Substring(0, Math.Min(viewer.Length, curViewer.Length)).Trim().ToLower()) - { - ViewerDenied = false; - break; - } - } + try + { + isChildAgent = avatar.IsChildAgent; + + m_log.DebugFormat( + "[SCENE]: Removing {0} agent {1} {2} from {3}", + isChildAgent ? "child" : "root", avatar.Name, agentID, Name); + + // Don't do this to root agents, it's not nice for the viewer + if (closeChildAgents && isChildAgent) + { + // Tell a single agent to disconnect from the region. + // Let's do this via UDP + avatar.ControllingClient.SendShutdownConnectionNotice(); + } + + // Only applies to root agents. + if (avatar.ParentID != 0) + { + avatar.StandUp(); + } + + m_sceneGraph.removeUserCount(!isChildAgent); + + // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop + // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI + if (closeChildAgents && CapsModule != null) + CapsModule.RemoveCaps(agentID); + + if (closeChildAgents && !isChildAgent) + { + List regions = avatar.KnownRegionHandles; + regions.Remove(RegionInfo.RegionHandle); + + // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours. + m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions); + } + + m_eventManager.TriggerClientClosed(agentID, this); + m_eventManager.TriggerOnRemovePresence(agentID); + + if (!isChildAgent) + { + if (AttachmentsModule != null) + { + AttachmentsModule.DeRezAttachments(avatar); + } + + ForEachClient( + delegate(IClientAPI client) + { + //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway + try { client.SendKillObject(new List { avatar.LocalId }); } + catch (NullReferenceException) { } + }); + } + + // It's possible for child agents to have transactions if changes are being made cross-border. + if (AgentTransactionsModule != null) + AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); } - else + catch (Exception e) { - ViewerDenied = false; - } - - //Check if the viewer is in the banned list - if (m_BannedViewers.Count > 0) - { - foreach (string viewer in m_BannedViewers) - { - if (viewer == curViewer.Substring(0, Math.Min(viewer.Length, curViewer.Length)).Trim().ToLower()) - { - ViewerDenied = true; - break; - } - } - } - - if (ViewerDenied) - { - m_log.DebugFormat( - "[SCENE]: Access denied for {0} {1} using {2}", - acd.firstname, acd.lastname, curViewer); - reason = "Access denied, your viewer is banned by the region owner"; - return false; - } - - ILandObject land; - ScenePresence sp; - - lock (m_removeClientLock) - { - sp = GetScenePresence(acd.AgentID); - - // We need to ensure that we are not already removing the scene presence before we ask it not to be - // closed. - if (sp != null && sp.IsChildAgent - && (sp.LifecycleState == ScenePresenceState.Running - || sp.LifecycleState == ScenePresenceState.PreRemove)) - { - m_log.DebugFormat( - "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}", - sp.Name, sp.LifecycleState, Name); - - // In the case where, for example, an A B C D region layout, an avatar may - // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C - // renews the lease on the child agent at B, we must make sure that the close from A does not succeed. - // - // XXX: In the end, this should not be necessary if child agents are closed without delay on - // teleport, since realistically, the close request should always be processed before any other - // region tried to re-establish a child agent. This is much simpler since the logic below is - // vulnerable to an issue when a viewer quits a region without sending a proper logout but then - // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport - // flag when no teleport had taken place (and hence no close was going to come). -// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle)) -// { -// m_log.DebugFormat( -// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.", -// sp.Name, Name); -// -// sp.DoNotCloseAfterTeleport = true; -// } -// else if (EntityTransferModule.IsInTransit(sp.UUID)) - - sp.LifecycleState = ScenePresenceState.Running; - - if (EntityTransferModule.IsInTransit(sp.UUID)) - { - sp.DoNotCloseAfterTeleport = true; - - m_log.DebugFormat( - "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.", - sp.Name, Name); - } - } - } - - // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will - // allow unpredictable things to happen. - if (sp != null) + m_log.Error( + string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); + } + finally + { + try + { + // Always clean these structures up so that any failure above doesn't cause them to remain in the + // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering + // the same cleanup exception continually. + m_authenticateHandler.RemoveCircuit(agentID); + m_sceneGraph.RemoveScenePresence(agentID); + m_clientManager.Remove(agentID); + + avatar.Close(); + } + catch (Exception e) + { + m_log.Error( + string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); + } + } + } + + //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); + //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); + } + + /// + /// Removes region from an avatar's known region list. This coincides with child agents. For each child agent, there will be a known region entry. + /// + /// + /// + /// + public void HandleRemoveKnownRegionsFromAvatar(UUID avatarID, List regionslst) + { + ScenePresence av = GetScenePresence(avatarID); + if (av != null) + { + lock (av) + { + for (int i = 0; i < regionslst.Count; i++) + { + av.RemoveNeighbourRegion(regionslst[i]); + } + } + } + } + + #endregion + + #region Entities + + public void SendKillObject(List localIDs) + { + List deleteIDs = new List(); + + foreach (uint localID in localIDs) + { + SceneObjectPart part = GetSceneObjectPart(localID); + if (part != null) // It is a prim + { + if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid + { + if (part.ParentGroup.RootPart != part) // Child part + continue; + } + } + deleteIDs.Add(localID); + } + + ForEachClient(c => c.SendKillObject(deleteIDs)); + } + + #endregion + + #region RegionComms + + /// + /// Do the work necessary to initiate a new user connection for a particular scene. + /// + /// CircuitData of the agent who is connecting + /// + /// Source region (may be null) + /// Outputs the reason for the false response on this string + /// True if the region accepts this agent. False if it does not. False will + /// also return a reason. + public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason) + { + return NewUserConnection(agent, teleportFlags, source, out reason, true); + } + + /// + /// Do the work necessary to initiate a new user connection for a particular scene. + /// + /// + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it yet, we still allowed banned users in. + /// + /// At the moment this method consists of setting up the caps infrastructure + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it let, we allowed banned users in still. + /// + /// This method is called by the login service (in the case of login) or another simulator (in the case of region + /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection + /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of + /// the LLUDP stack). + /// + /// CircuitData of the agent who is connecting + /// Source region (may be null) + /// Outputs the reason for the false response on this string + /// True for normal presence. False for NPC + /// or other applications where a full grid/Hypergrid presence may not be required. + /// True if the region accepts this agent. False if it does not. False will + /// also return a reason. + public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup) + { + bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || + (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); + bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0); + bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0); + + reason = String.Empty; + + //Teleport flags: + // + // TeleportFlags.ViaGodlikeLure - Border Crossing + // TeleportFlags.ViaLogin - Login + // TeleportFlags.TeleportFlags.ViaLure - Teleport request sent by another user + // TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport + + // Don't disable this log message - it's too helpful + string curViewer = Util.GetViewerName(acd); + m_log.DebugFormat( + "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9}. {10}", + RegionInfo.RegionName, + (acd.child ? "child" : "root"), + acd.firstname, + acd.lastname, + acd.AgentID, + acd.circuitcode, + acd.IPAddress, + curViewer, + ((TPFlags)teleportFlags).ToString(), + acd.startpos, + (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI) + ); + + if (!LoginsEnabled) + { + reason = "Logins Disabled"; + return false; + } + + //Check if the viewer is banned or in the viewer access list + //We check if the substring is listed for higher flexebility + bool ViewerDenied = true; + + //Check if the specific viewer is listed in the allowed viewer list + if (m_AllowedViewers.Count > 0) + { + foreach (string viewer in m_AllowedViewers) + { + if (viewer == curViewer.Substring(0, Math.Min(viewer.Length, curViewer.Length)).Trim().ToLower()) + { + ViewerDenied = false; + break; + } + } + } + else + { + ViewerDenied = false; + } + + //Check if the viewer is in the banned list + if (m_BannedViewers.Count > 0) + { + foreach (string viewer in m_BannedViewers) + { + if (viewer == curViewer.Substring(0, Math.Min(viewer.Length, curViewer.Length)).Trim().ToLower()) + { + ViewerDenied = true; + break; + } + } + } + + if (ViewerDenied) + { + m_log.DebugFormat( + "[SCENE]: Access denied for {0} {1} using {2}", + acd.firstname, acd.lastname, curViewer); + reason = "Access denied, your viewer is banned by the region owner"; + return false; + } + + ILandObject land; + ScenePresence sp; + + lock (m_removeClientLock) + { + sp = GetScenePresence(acd.AgentID); + + // We need to ensure that we are not already removing the scene presence before we ask it not to be + // closed. + if (sp != null && sp.IsChildAgent + && (sp.LifecycleState == ScenePresenceState.Running + || sp.LifecycleState == ScenePresenceState.PreRemove)) + { + m_log.DebugFormat( + "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}", + sp.Name, sp.LifecycleState, Name); + + // In the case where, for example, an A B C D region layout, an avatar may + // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C + // renews the lease on the child agent at B, we must make sure that the close from A does not succeed. + // + // XXX: In the end, this should not be necessary if child agents are closed without delay on + // teleport, since realistically, the close request should always be processed before any other + // region tried to re-establish a child agent. This is much simpler since the logic below is + // vulnerable to an issue when a viewer quits a region without sending a proper logout but then + // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport + // flag when no teleport had taken place (and hence no close was going to come). + // if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle)) + // { + // m_log.DebugFormat( + // "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.", + // sp.Name, Name); + // + // sp.DoNotCloseAfterTeleport = true; + // } + // else if (EntityTransferModule.IsInTransit(sp.UUID)) + + sp.LifecycleState = ScenePresenceState.Running; + + if (EntityTransferModule.IsInTransit(sp.UUID)) + { + sp.DoNotCloseAfterTeleport = true; + + m_log.DebugFormat( + "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.", + sp.Name, Name); + } + } + } + + // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will + // allow unpredictable things to happen. + if (sp != null) + { + const int polls = 10; + const int pollInterval = 1000; + int pollsLeft = polls; + + while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0) + Thread.Sleep(pollInterval); + + if (sp.LifecycleState == ScenePresenceState.Removing) + { + m_log.WarnFormat( + "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.", + sp.Name, Name, polls * pollInterval / 1000); + + return false; + } + else if (polls != pollsLeft) + { + m_log.DebugFormat( + "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.", + sp.Name, Name, polls * pollInterval / 1000); + } + } + + // TODO: can we remove this lock? + lock (acd) + { + if (sp != null && !sp.IsChildAgent) + { + // We have a root agent. Is it in transit? + if (!EntityTransferModule.IsInTransit(sp.UUID)) + { + // We have a zombie from a crashed session. + // Or the same user is trying to be root twice here, won't work. + // Kill it. + m_log.WarnFormat( + "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", + sp.Name, sp.UUID, RegionInfo.RegionName); + + if (sp.ControllingClient != null) + CloseAgent(sp.UUID, true); + + sp = null; + } + //else + // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName); + } + + // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags. + // We need the circuit data here for some of the subsequent checks. (groups, for example) + // If the checks fail, we remove the circuit. + acd.teleportFlags = teleportFlags; + m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); + + land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y); + + // On login test land permisions + if (vialogin) { - const int polls = 10; - const int pollInterval = 1000; - int pollsLeft = polls; - - while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0) - Thread.Sleep(pollInterval); - - if (sp.LifecycleState == ScenePresenceState.Removing) - { - m_log.WarnFormat( - "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.", - sp.Name, Name, polls * pollInterval / 1000); - - return false; - } - else if (polls != pollsLeft) - { - m_log.DebugFormat( - "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.", - sp.Name, Name, polls * pollInterval / 1000); - } - } - - // TODO: can we remove this lock? - lock (acd) - { - if (sp != null && !sp.IsChildAgent) - { - // We have a root agent. Is it in transit? - if (!EntityTransferModule.IsInTransit(sp.UUID)) - { - // We have a zombie from a crashed session. - // Or the same user is trying to be root twice here, won't work. - // Kill it. - m_log.WarnFormat( - "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", - sp.Name, sp.UUID, RegionInfo.RegionName); - - if (sp.ControllingClient != null) - CloseAgent(sp.UUID, true); - - sp = null; - } - //else - // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName); - } - - // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags. - // We need the circuit data here for some of the subsequent checks. (groups, for example) - // If the checks fail, we remove the circuit. - acd.teleportFlags = teleportFlags; - m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); - - land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y); - - // On login test land permisions - if (vialogin) - { - if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - } - - if (sp == null) // We don't have an [child] agent here already - { - if (requirePresenceLookup) - { - try - { - if (!VerifyUserPresence(acd, out reason)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - } - catch (Exception e) - { - m_log.ErrorFormat( - "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); - - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - } - - try - { - if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - } - catch (Exception e) - { - m_log.ErrorFormat( - "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); - - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - - m_log.InfoFormat( - "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", - Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname, - acd.AgentID, acd.circuitcode); - - if (CapsModule != null) - { - CapsModule.SetAgentCapsSeeds(acd); - CapsModule.CreateCaps(acd.AgentID); - } - } - else - { - // Let the SP know how we got here. This has a lot of interesting - // uses down the line. - sp.TeleportFlags = (TPFlags)teleportFlags; - - if (sp.IsChildAgent) - { - m_log.DebugFormat( - "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", - acd.AgentID, RegionInfo.RegionName); - - sp.AdjustKnownSeeds(); - - if (CapsModule != null) - { - CapsModule.SetAgentCapsSeeds(acd); - CapsModule.CreateCaps(acd.AgentID); - } - } - } - - // Try caching an incoming user name much earlier on to see if this helps with an issue - // where HG users are occasionally seen by others as "Unknown User" because their UUIDName - // request for the HG avatar appears to trigger before the user name is cached. - CacheUserName(null, acd); + if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) + { + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } } - if (vialogin) + if (sp == null) // We don't have an [child] agent here already { -// CleanDroppedAttachments(); - - // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking) - if (acd.startpos.X < 0) acd.startpos.X = 1f; - if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f; - if (acd.startpos.Y < 0) acd.startpos.Y = 1f; - if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f; - -// m_log.DebugFormat( -// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}", -// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); - - // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags - if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && - RegionInfo.EstateSettings.AllowDirectTeleport == false && - !viahome && !godlike) - { - SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); - - if (telehub != null) - { - // Can have multiple SpawnPoints - List spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); - if (spawnpoints.Count > 1) - { - // We have multiple SpawnPoints, Route the agent to a random or sequential one - if (SpawnPointRouting == "random") - acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( - telehub.AbsolutePosition, - telehub.GroupRotation - ); - else - acd.startpos = spawnpoints[SpawnPoint()].GetLocation( - telehub.AbsolutePosition, - telehub.GroupRotation - ); - } - else if (spawnpoints.Count == 1) - { - // We have a single SpawnPoint and will route the agent to it - acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); - } - else - { - m_log.DebugFormat( - "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.", - RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); - } - } - else - { - m_log.DebugFormat( - "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.", - RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); - } - - // Final permissions check; this time we don't allow changing the position - if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) - { + if (requirePresenceLookup) + { + try + { + if (!VerifyUserPresence(acd, out reason)) + { m_authenticateHandler.RemoveCircuit(acd.circuitcode); return false; - } - - return true; - } - - // Honor parcel landing type and position. - if (land != null) - { - if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) - { - acd.startpos = land.LandData.UserLocation; - - // Final permissions check; this time we don't allow changing the position - if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - } - } + } + } + catch (Exception e) + { + m_log.ErrorFormat( + "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); + + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + } + + try + { + if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason)) + { + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + } + catch (Exception e) + { + m_log.ErrorFormat( + "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); + + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + + m_log.InfoFormat( + "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", + Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname, + acd.AgentID, acd.circuitcode); + + if (CapsModule != null) + { + CapsModule.SetAgentCapsSeeds(acd); + CapsModule.CreateCaps(acd.AgentID); + } } + else + { + // Let the SP know how we got here. This has a lot of interesting + // uses down the line. + sp.TeleportFlags = (TPFlags)teleportFlags; + + if (sp.IsChildAgent) + { + m_log.DebugFormat( + "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", + acd.AgentID, RegionInfo.RegionName); + + sp.AdjustKnownSeeds(); + + if (CapsModule != null) + { + CapsModule.SetAgentCapsSeeds(acd); + CapsModule.CreateCaps(acd.AgentID); + } + } + } + + // Try caching an incoming user name much earlier on to see if this helps with an issue + // where HG users are occasionally seen by others as "Unknown User" because their UUIDName + // request for the HG avatar appears to trigger before the user name is cached. + CacheUserName(null, acd); + } + + if (vialogin) + { + // CleanDroppedAttachments(); + + // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking) + if (acd.startpos.X < 0) acd.startpos.X = 1f; + if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f; + if (acd.startpos.Y < 0) acd.startpos.Y = 1f; + if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f; + + // m_log.DebugFormat( + // "[SCENE]: Found telehub object {0} for new user connection {1} to {2}", + // RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); + + // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags + if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && + RegionInfo.EstateSettings.AllowDirectTeleport == false && + !viahome && !godlike) + { + SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); + + if (telehub != null) + { + // Can have multiple SpawnPoints + List spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); + if (spawnpoints.Count > 1) + { + // We have multiple SpawnPoints, Route the agent to a random or sequential one + if (SpawnPointRouting == "random") + acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( + telehub.AbsolutePosition, + telehub.GroupRotation + ); + else + acd.startpos = spawnpoints[SpawnPoint()].GetLocation( + telehub.AbsolutePosition, + telehub.GroupRotation + ); + } + else if (spawnpoints.Count == 1) + { + // We have a single SpawnPoint and will route the agent to it + acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + } + else + { + m_log.DebugFormat( + "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.", + RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); + } + } + else + { + m_log.DebugFormat( + "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.", + RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); + } + + // Final permissions check; this time we don't allow changing the position + if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) + { + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + + return true; + } + + // Honor parcel landing type and position. + if (land != null) + { + if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) + { + acd.startpos = land.LandData.UserLocation; + + // Final permissions check; this time we don't allow changing the position + if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) + { + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + } + } + } + + return true; + } + + private bool IsPositionAllowed(UUID agentID, Vector3 pos, ref string reason) + { + ILandObject land = LandChannel.GetLandObject(pos); + if (land == null) + return true; + if (land.IsBannedFromLand(agentID) || land.IsRestrictedFromLand(agentID)) + { + reason = "You are banned from the region."; + return false; + } + + return true; + } + + public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY) + { + if (posX < 0) + posX = 0; + else if (posX >= (float)RegionInfo.RegionSizeX) + posX = (float)RegionInfo.RegionSizeX - 0.001f; + if (posY < 0) + posY = 0; + else if (posY >= (float)RegionInfo.RegionSizeY) + posY = (float)RegionInfo.RegionSizeY - 0.001f; + + reason = String.Empty; + if (Permissions.IsGod(agentID)) return true; - } - private bool IsPositionAllowed(UUID agentID, Vector3 pos, ref string reason) - { - ILandObject land = LandChannel.GetLandObject(pos); - if (land == null) - return true; + ILandObject land = LandChannel.GetLandObject(posX, posY); + if (land == null) + return false; + + bool banned = land.IsBannedFromLand(agentID); + bool restricted = land.IsRestrictedFromLand(agentID); - if (land.IsBannedFromLand(agentID) || land.IsRestrictedFromLand(agentID)) + if (banned || restricted) + { + ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY); + if (nearestParcel != null) { - reason = "You are banned from the region."; - return false; + //Move agent to nearest allowed + Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); + posX = newPosition.X; + posY = newPosition.Y; } + else + { + if (banned) + { + reason = "Cannot regioncross into banned parcel."; + } + else + { + reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", + RegionInfo.RegionName); + } + return false; + } + } + reason = ""; + return true; + } + + /// + /// Verifies that the user has a presence on the Grid + /// + /// Circuit Data of the Agent we're verifying + /// Outputs the reason for the false response on this string + /// True if the user has a session on the grid. False if it does not. False will + /// also return a reason. + public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason) + { + reason = String.Empty; + + IPresenceService presence = RequestModuleInterface(); + if (presence == null) + { + reason = String.Format("Failed to verify user presence in the grid for {0} {1} in region {2}. Presence service does not exist.", agent.firstname, agent.lastname, RegionInfo.RegionName); + return false; + } - return true; - } - - public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY) - { - if (posX < 0) - posX = 0; - else if (posX >= (float)RegionInfo.RegionSizeX) - posX = (float)RegionInfo.RegionSizeX - 0.001f; - if (posY < 0) - posY = 0; - else if (posY >= (float)RegionInfo.RegionSizeY) - posY = (float)RegionInfo.RegionSizeY - 0.001f; + OpenSim.Services.Interfaces.PresenceInfo pinfo = presence.GetAgent(agent.SessionID); - reason = String.Empty; - if (Permissions.IsGod(agentID)) - return true; + if (pinfo == null) + { + reason = String.Format("Failed to verify user presence in the grid for {0} {1}, access denied to region {2}.", agent.firstname, agent.lastname, RegionInfo.RegionName); + return false; + } + + return true; + } + + /// + /// Verify if the user can connect to this region. Checks the banlist and ensures that the region is set for public access + /// + /// The circuit data for the agent + /// outputs the reason to this string + /// True if the region accepts this agent. False if it does not. False will + /// also return a reason. + protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason) + { + reason = String.Empty; + + if (!m_strictAccessControl) return true; + if (Permissions.IsGod(agent.AgentID)) return true; + + if (AuthorizationService != null) + { + if (!AuthorizationService.IsAuthorizedForRegion( + agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason)) + { + m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because: {4}", + agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName, reason); + + return false; + } + } + + // We only test the things below when we want to cut off + // child agents from being present in the scene for which their root + // agent isn't allowed. Otherwise, we allow child agents. The test for + // the root is done elsewhere (QueryAccess) + if (!bypassAccessControl) + { + if (RegionInfo.EstateSettings != null) + { + if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) + { + m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", + agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + reason = String.Format("Denied access to region {0}: You have been banned from that region.", + RegionInfo.RegionName); + return false; + } + } + else + { + m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); + } - ILandObject land = LandChannel.GetLandObject(posX, posY); - if (land == null) - return false; + List agentGroups = new List(); - bool banned = land.IsBannedFromLand(agentID); - bool restricted = land.IsRestrictedFromLand(agentID); - - if (banned || restricted) + if (m_groupsModule != null) { - ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY); - if (nearestParcel != null) - { - //Move agent to nearest allowed - Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); - posX = newPosition.X; - posY = newPosition.Y; - } - else - { - if (banned) - { - reason = "Cannot regioncross into banned parcel."; - } - else - { - reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", - RegionInfo.RegionName); - } - return false; - } - } - reason = ""; - return true; - } - - /// - /// Verifies that the user has a presence on the Grid - /// - /// Circuit Data of the Agent we're verifying - /// Outputs the reason for the false response on this string - /// True if the user has a session on the grid. False if it does not. False will - /// also return a reason. - public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason) - { - reason = String.Empty; + GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); - IPresenceService presence = RequestModuleInterface(); - if (presence == null) - { - reason = String.Format("Failed to verify user presence in the grid for {0} {1} in region {2}. Presence service does not exist.", agent.firstname, agent.lastname, RegionInfo.RegionName); - return false; + if (GroupMembership != null) + { + for (int i = 0; i < GroupMembership.Length; i++) + agentGroups.Add(GroupMembership[i].GroupID); + } + else + { + m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); + } } - OpenSim.Services.Interfaces.PresenceInfo pinfo = presence.GetAgent(agent.SessionID); + bool groupAccess = false; + UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; - if (pinfo == null) + if (estateGroups != null) { - reason = String.Format("Failed to verify user presence in the grid for {0} {1}, access denied to region {2}.", agent.firstname, agent.lastname, RegionInfo.RegionName); - return false; + foreach (UUID group in estateGroups) + { + if (agentGroups.Contains(group)) + { + groupAccess = true; + break; + } + } } + else + { + m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); + } + + if (!RegionInfo.EstateSettings.PublicAccess && + !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && + !groupAccess) + { + m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", + agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", + RegionInfo.RegionName); + return false; + } + } + + // TODO: estate/region settings are not properly hooked up + // to ILandObject.isRestrictedFromLand() + // if (null != LandChannel) + // { + // // region seems to have local Id of 1 + // ILandObject land = LandChannel.GetLandObject(1); + // if (null != land) + // { + // if (land.isBannedFromLand(agent.AgentID)) + // { + // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land", + // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + // reason = String.Format("Denied access to private region {0}: You are banned from that region.", + // RegionInfo.RegionName); + // return false; + // } + + // if (land.isRestrictedFromLand(agent.AgentID)) + // { + // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", + // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", + // RegionInfo.RegionName); + // return false; + // } + // } + // } + + return true; + } + + /// + /// Update an AgentCircuitData object with new information + /// + /// Information to update the AgentCircuitData with + public void UpdateCircuitData(AgentCircuitData data) + { + m_authenticateHandler.UpdateAgentData(data); + } + + /// + /// Change the Circuit Code for the user's Circuit Data + /// + /// The old Circuit Code. Must match a previous circuit code + /// The new Circuit Code. Must not be an already existing circuit code + /// True if we successfully changed it. False if we did not + public bool ChangeCircuitCode(uint oldcc, uint newcc) + { + return m_authenticateHandler.TryChangeCiruitCode(oldcc, newcc); + } + + // /// + // /// The Grid has requested that we log-off a user. Log them off. + // /// + // /// Unique ID of the avatar to log-off + // /// SecureSessionID of the user, or the RegionSecret text when logging on to the grid + // /// message to display to the user. Reason for being logged off + // public void HandleLogOffUserFromGrid(UUID AvatarID, UUID RegionSecret, string message) + // { + // ScenePresence loggingOffUser = GetScenePresence(AvatarID); + // if (loggingOffUser != null) + // { + // UUID localRegionSecret = UUID.Zero; + // bool parsedsecret = UUID.TryParse(RegionInfo.regionSecret, out localRegionSecret); + // + // // Region Secret is used here in case a new sessionid overwrites an old one on the user server. + // // Will update the user server in a few revisions to use it. + // + // if (RegionSecret == loggingOffUser.ControllingClient.SecureSessionId || (parsedsecret && RegionSecret == localRegionSecret)) + // { + // m_sceneGridService.SendCloseChildAgentConnections(loggingOffUser.UUID, loggingOffUser.KnownRegionHandles); + // loggingOffUser.ControllingClient.Kick(message); + // // Give them a second to receive the message! + // Thread.Sleep(1000); + // loggingOffUser.ControllingClient.Close(); + // } + // else + // { + // m_log.Info("[USERLOGOFF]: System sending the LogOff user message failed to sucessfully authenticate"); + // } + // } + // else + // { + // m_log.InfoFormat("[USERLOGOFF]: Got a logoff request for {0} but the user isn't here. The user might already have been logged out", AvatarID.ToString()); + // } + // } + + // /// + // /// Triggered when an agent crosses into this sim. Also happens on initial login. + // /// + // /// + // /// + // /// + // public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying) + // { + // ScenePresence presence = GetScenePresence(agentID); + // if (presence != null) + // { + // try + // { + // presence.MakeRootAgent(position, isFlying); + // } + // catch (Exception e) + // { + // m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace); + // } + // } + // else + // { + // m_log.ErrorFormat( + // "[SCENE]: Could not find presence for agent {0} crossing into scene {1}", + // agentID, RegionInfo.RegionName); + // } + // } + + /// + /// We've got an update about an agent that sees into this region, + /// send it to ScenePresence for processing It's the full data. + /// + /// Agent that contains all of the relevant things about an agent. + /// Appearance, animations, position, etc. + /// true if we handled it. + public virtual bool IncomingUpdateChildAgent(AgentData cAgentData) + { + m_log.DebugFormat( + "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); + + // TODO: This check should probably be in QueryAccess(). + ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2); + if (nearestParcel == null) + { + m_log.InfoFormat( + "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", + cAgentData.AgentID, RegionInfo.RegionName); - return true; - } - - /// - /// Verify if the user can connect to this region. Checks the banlist and ensures that the region is set for public access - /// - /// The circuit data for the agent - /// outputs the reason to this string - /// True if the region accepts this agent. False if it does not. False will - /// also return a reason. - protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason) - { - reason = String.Empty; - - if (!m_strictAccessControl) return true; - if (Permissions.IsGod(agent.AgentID)) return true; - - if (AuthorizationService != null) - { - if (!AuthorizationService.IsAuthorizedForRegion( - agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason)) - { - m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because: {4}", - agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName, reason); - - return false; - } - } - - // We only test the things below when we want to cut off - // child agents from being present in the scene for which their root - // agent isn't allowed. Otherwise, we allow child agents. The test for - // the root is done elsewhere (QueryAccess) - if (!bypassAccessControl) - { - if (RegionInfo.EstateSettings != null) - { - if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) - { - m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", - agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - reason = String.Format("Denied access to region {0}: You have been banned from that region.", - RegionInfo.RegionName); - return false; - } - } - else - { - m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); - } - - List agentGroups = new List(); - - if (m_groupsModule != null) - { - GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); - - if (GroupMembership != null) - { - for (int i = 0; i < GroupMembership.Length; i++) - agentGroups.Add(GroupMembership[i].GroupID); - } - else - { - m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); - } - } - - bool groupAccess = false; - UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; - - if (estateGroups != null) - { - foreach (UUID group in estateGroups) - { - if (agentGroups.Contains(group)) - { - groupAccess = true; - break; - } - } - } - else - { - m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); - } - - if (!RegionInfo.EstateSettings.PublicAccess && - !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && - !groupAccess) - { - m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", - agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", - RegionInfo.RegionName); - return false; - } - } - - // TODO: estate/region settings are not properly hooked up - // to ILandObject.isRestrictedFromLand() - // if (null != LandChannel) - // { - // // region seems to have local Id of 1 - // ILandObject land = LandChannel.GetLandObject(1); - // if (null != land) - // { - // if (land.isBannedFromLand(agent.AgentID)) - // { - // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land", - // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - // reason = String.Format("Denied access to private region {0}: You are banned from that region.", - // RegionInfo.RegionName); - // return false; - // } - - // if (land.isRestrictedFromLand(agent.AgentID)) - // { - // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", - // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", - // RegionInfo.RegionName); - // return false; - // } - // } - // } + return false; + } - return true; - } - - /// - /// Update an AgentCircuitData object with new information - /// - /// Information to update the AgentCircuitData with - public void UpdateCircuitData(AgentCircuitData data) - { - m_authenticateHandler.UpdateAgentData(data); - } - - /// - /// Change the Circuit Code for the user's Circuit Data - /// - /// The old Circuit Code. Must match a previous circuit code - /// The new Circuit Code. Must not be an already existing circuit code - /// True if we successfully changed it. False if we did not - public bool ChangeCircuitCode(uint oldcc, uint newcc) - { - return m_authenticateHandler.TryChangeCiruitCode(oldcc, newcc); - } - -// /// -// /// The Grid has requested that we log-off a user. Log them off. -// /// -// /// Unique ID of the avatar to log-off -// /// SecureSessionID of the user, or the RegionSecret text when logging on to the grid -// /// message to display to the user. Reason for being logged off -// public void HandleLogOffUserFromGrid(UUID AvatarID, UUID RegionSecret, string message) -// { -// ScenePresence loggingOffUser = GetScenePresence(AvatarID); -// if (loggingOffUser != null) -// { -// UUID localRegionSecret = UUID.Zero; -// bool parsedsecret = UUID.TryParse(RegionInfo.regionSecret, out localRegionSecret); -// -// // Region Secret is used here in case a new sessionid overwrites an old one on the user server. -// // Will update the user server in a few revisions to use it. -// -// if (RegionSecret == loggingOffUser.ControllingClient.SecureSessionId || (parsedsecret && RegionSecret == localRegionSecret)) -// { -// m_sceneGridService.SendCloseChildAgentConnections(loggingOffUser.UUID, loggingOffUser.KnownRegionHandles); -// loggingOffUser.ControllingClient.Kick(message); -// // Give them a second to receive the message! -// Thread.Sleep(1000); -// loggingOffUser.ControllingClient.Close(); -// } -// else -// { -// m_log.Info("[USERLOGOFF]: System sending the LogOff user message failed to sucessfully authenticate"); -// } -// } -// else -// { -// m_log.InfoFormat("[USERLOGOFF]: Got a logoff request for {0} but the user isn't here. The user might already have been logged out", AvatarID.ToString()); -// } -// } - -// /// -// /// Triggered when an agent crosses into this sim. Also happens on initial login. -// /// -// /// -// /// -// /// -// public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying) -// { -// ScenePresence presence = GetScenePresence(agentID); -// if (presence != null) -// { -// try -// { -// presence.MakeRootAgent(position, isFlying); -// } -// catch (Exception e) -// { -// m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace); -// } -// } -// else -// { -// m_log.ErrorFormat( -// "[SCENE]: Could not find presence for agent {0} crossing into scene {1}", -// agentID, RegionInfo.RegionName); -// } -// } - - /// - /// We've got an update about an agent that sees into this region, - /// send it to ScenePresence for processing It's the full data. - /// - /// Agent that contains all of the relevant things about an agent. - /// Appearance, animations, position, etc. - /// true if we handled it. - public virtual bool IncomingUpdateChildAgent(AgentData cAgentData) - { - m_log.DebugFormat( - "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); + // We have to wait until the viewer contacts this region + // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol) + // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send + // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. + ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); - // TODO: This check should probably be in QueryAccess(). - ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2); - if (nearestParcel == null) + if (sp != null) + { + if (cAgentData.SessionID != sp.ControllingClient.SessionId) { - m_log.InfoFormat( - "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", - cAgentData.AgentID, RegionInfo.RegionName); + m_log.WarnFormat( + "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", + sp.UUID, cAgentData.SessionID); - return false; + Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}", + sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); } - // We have to wait until the viewer contacts this region - // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol) - // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send - // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. - ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); + sp.UpdateChildAgent(cAgentData); - if (sp != null) + int ntimes = 20; + if (cAgentData.SenderWantsToWaitForRoot) { - if (cAgentData.SessionID != sp.ControllingClient.SessionId) - { - m_log.WarnFormat( - "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", - sp.UUID, cAgentData.SessionID); - - Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}", - sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); - } - - sp.UpdateChildAgent(cAgentData); - - int ntimes = 20; - if (cAgentData.SenderWantsToWaitForRoot) - { - while (sp.IsChildAgent && ntimes-- > 0) - Thread.Sleep(1000); - - if (sp.IsChildAgent) - m_log.WarnFormat( - "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}", - sp.Name, sp.UUID, Name); - else - m_log.InfoFormat( - "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits", - sp.Name, sp.UUID, Name, 20 - ntimes); - - if (sp.IsChildAgent) - return false; - } + while (sp.IsChildAgent && ntimes-- > 0) + Thread.Sleep(1000); - return true; - } + if (sp.IsChildAgent) + m_log.WarnFormat( + "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}", + sp.Name, sp.UUID, Name); + else + m_log.InfoFormat( + "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits", + sp.Name, sp.UUID, Name, 20 - ntimes); - return false; - } - - /// - /// We've got an update about an agent that sees into this region, - /// send it to ScenePresence for processing It's only positional data - /// - /// AgentPosition that contains agent positional data so we can know what to send - /// true if we handled it. - public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData) - { -// m_log.DebugFormat( -// "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}", -// cAgentData.AgentID, Name, cAgentData.Position); - - ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); - if (childAgentUpdate != null) - { -// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID) -// // Only warn for now -// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?", -// childAgentUpdate.UUID, cAgentData.SessionID); - - // I can't imagine *yet* why we would get an update if the agent is a root agent.. - // however to avoid a race condition crossing borders.. - if (childAgentUpdate.IsChildAgent) - { - uint rRegionX = (uint)(cAgentData.RegionHandle >> 40); - uint rRegionY = (((uint)(cAgentData.RegionHandle)) >> 8); - uint tRegionX = RegionInfo.RegionLocX; - uint tRegionY = RegionInfo.RegionLocY; - //Send Data to ScenePresence - childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); - // Not Implemented: - //TODO: Do we need to pass the message on to one of our neighbors? - } - - return true; + if (sp.IsChildAgent) + return false; } - return false; - } - - /// - /// Poll until the requested ScenePresence appears or we timeout. - /// - /// The scene presence is found, else null. - /// - protected virtual ScenePresence WaitGetScenePresence(UUID agentID) - { - int ntimes = 20; - ScenePresence sp = null; - while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) - Thread.Sleep(1000); - - if (sp == null) - m_log.WarnFormat( - "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", - agentID, RegionInfo.RegionName); + return true; + } + + return false; + } + + /// + /// We've got an update about an agent that sees into this region, + /// send it to ScenePresence for processing It's only positional data + /// + /// AgentPosition that contains agent positional data so we can know what to send + /// true if we handled it. + public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData) + { + // m_log.DebugFormat( + // "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}", + // cAgentData.AgentID, Name, cAgentData.Position); + + ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); + if (childAgentUpdate != null) + { + // if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID) + // // Only warn for now + // m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?", + // childAgentUpdate.UUID, cAgentData.SessionID); + + // I can't imagine *yet* why we would get an update if the agent is a root agent.. + // however to avoid a race condition crossing borders.. + if (childAgentUpdate.IsChildAgent) + { + uint rRegionX = (uint)(cAgentData.RegionHandle >> 40); + uint rRegionY = (((uint)(cAgentData.RegionHandle)) >> 8); + uint tRegionX = RegionInfo.RegionLocX; + uint tRegionY = RegionInfo.RegionLocY; + //Send Data to ScenePresence + childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); + // Not Implemented: + //TODO: Do we need to pass the message on to one of our neighbors? + } - return sp; - } + return true; + } + + return false; + } + + /// + /// Poll until the requested ScenePresence appears or we timeout. + /// + /// The scene presence is found, else null. + /// + protected virtual ScenePresence WaitGetScenePresence(UUID agentID) + { + int ntimes = 20; + ScenePresence sp = null; + while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) + Thread.Sleep(1000); + + if (sp == null) + m_log.WarnFormat( + "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", + agentID, RegionInfo.RegionName); + + return sp; + } + + /// + /// Authenticated close (via network) + /// + /// + /// + /// + /// + public bool CloseAgent(UUID agentID, bool force, string auth_token) + { + //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token); + + // Check that the auth_token is valid + AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID); + + if (acd == null) + { + m_log.DebugFormat( + "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.", + agentID, Name); - /// - /// Authenticated close (via network) - /// - /// - /// - /// - /// - public bool CloseAgent(UUID agentID, bool force, string auth_token) - { - //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token); + return false; + } + + if (acd.SessionID.ToString() == auth_token) + { + return CloseAgent(agentID, force); + } + else + { + m_log.WarnFormat( + "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}", + agentID, auth_token, Name); + } + + return false; + } + + /// + /// Tell a single client to prepare to close. + /// + /// + /// This should only be called if we may close the client but there will be some delay in so doing. Meant for + /// internal use - other callers should almost certainly called CloseClient(). + /// + /// + /// true if pre-close state notification was successful. false if the agent + /// was not in a state where it could transition to pre-close. + public bool IncomingPreCloseClient(ScenePresence sp) + { + lock (m_removeClientLock) + { + // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may + // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not + // want to obey this close since C may have renewed the child agent lease on B. + if (sp.DoNotCloseAfterTeleport) + { + m_log.DebugFormat( + "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection", + sp.IsChildAgent ? "child" : "root", sp.Name, Name); + + // Need to reset the flag so that a subsequent close after another teleport can succeed. + sp.DoNotCloseAfterTeleport = false; + + return false; + } + + if (sp.LifecycleState != ScenePresenceState.Running) + { + m_log.DebugFormat( + "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}", + sp.Name, Name, sp.LifecycleState); + + return false; + } + + sp.LifecycleState = ScenePresenceState.PreRemove; - // Check that the auth_token is valid - AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID); + return true; + } + } + + /// + /// Tell a single agent to disconnect from the region. + /// + /// + /// + /// Force the agent to close even if it might be in the middle of some other operation. You do not want to + /// force unless you are absolutely sure that the agent is dead and a normal close is not working. + /// + public override bool CloseAgent(UUID agentID, bool force) + { + ScenePresence sp; + + lock (m_removeClientLock) + { + sp = GetScenePresence(agentID); - if (acd == null) + if (sp == null) { - m_log.DebugFormat( - "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.", - agentID, Name); - - return false; - } - - if (acd.SessionID.ToString() == auth_token) + m_log.DebugFormat( + "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", + agentID, Name); + + return false; + } + + if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove) + { + m_log.DebugFormat( + "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}", + sp.Name, Name, sp.LifecycleState); + + return false; + } + + // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may + // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not + // want to obey this close since C may have renewed the child agent lease on B. + if (sp.DoNotCloseAfterTeleport) + { + m_log.DebugFormat( + "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection", + sp.IsChildAgent ? "child" : "root", sp.Name, Name); + + // Need to reset the flag so that a subsequent close after another teleport can succeed. + sp.DoNotCloseAfterTeleport = false; + + return false; + } + + sp.LifecycleState = ScenePresenceState.Removing; + } + + sp.ControllingClient.Close(force); + + return true; + } + + /// + /// Tries to teleport agent to another region. + /// + /// + /// The region name must exactly match that given. + /// + /// + /// + /// + /// + /// + public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, + Vector3 lookat, uint teleportFlags) + { + GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName); + + if (region == null) + { + // can't find the region: Tell viewer and abort + remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); + return; + } + + RequestTeleportLocation(remoteClient, region.RegionHandle, position, lookat, teleportFlags); + } + + /// + /// Tries to teleport agent to other region. + /// + /// + /// + /// + /// + /// + public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, + Vector3 lookAt, uint teleportFlags) + { + ScenePresence sp = GetScenePresence(remoteClient.AgentId); + if (sp != null) + { + if (EntityTransferModule != null) { - return CloseAgent(agentID, force); + EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); } else { - m_log.WarnFormat( - "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}", - agentID, auth_token, Name); + m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active"); + sp.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator."); + } + } + } + + public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) + { + if (EntityTransferModule != null) + { + return EntityTransferModule.Cross(agent, isFlying); + } + else + { + m_log.DebugFormat("[SCENE]: Unable to cross agent to neighbouring region, because there is no AgentTransferModule"); + } + + return false; + } + + public void SendOutChildAgentUpdates(AgentPosition cadu, ScenePresence presence) + { + m_sceneGridService.SendChildAgentDataUpdate(cadu, presence); + } + + #endregion + + #region Other Methods + + protected override IConfigSource GetConfig() + { + return m_config; + } + + #endregion + + public void HandleObjectPermissionsUpdate(IClientAPI controller, UUID agentID, UUID sessionID, byte field, uint localId, uint mask, byte set) + { + // Check for spoofing.. since this is permissions we're talking about here! + if ((controller.SessionId == sessionID) && (controller.AgentId == agentID)) + { + // Tell the object to do permission update + if (localId != 0) + { + SceneObjectGroup chObjectGroup = GetGroupByPrim(localId); + if (chObjectGroup != null) + { + chObjectGroup.UpdatePermissions(agentID, field, localId, mask, set); + } + } + } + } + + /// + /// Causes all clients to get a full object update on all of the objects in the scene. + /// + public void ForceClientUpdate() + { + EntityBase[] entityList = GetEntities(); + foreach (EntityBase ent in entityList) + { + if (ent is SceneObjectGroup) + { + ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); + } + } + } + + /// + /// This is currently only used for scale (to scale to MegaPrim size) + /// There is a console command that calls this in OpenSimMain + /// + /// + public void HandleEditCommand(string[] cmdparams) + { + m_log.DebugFormat("Searching for Primitive: '{0}'", cmdparams[2]); + + EntityBase[] entityList = GetEntities(); + foreach (EntityBase ent in entityList) + { + if (ent is SceneObjectGroup) + { + SceneObjectPart part = ((SceneObjectGroup)ent).GetPart(((SceneObjectGroup)ent).UUID); + if (part != null) + { + if (part.Name == cmdparams[2]) + { + part.Resize( + new Vector3(Convert.ToSingle(cmdparams[3]), Convert.ToSingle(cmdparams[4]), + Convert.ToSingle(cmdparams[5]))); + + m_log.DebugFormat("Edited scale of Primitive: {0}", part.Name); + } + } + } + } + } + + #region Script Handling Methods + + /// + /// Console command handler to send script command to script engine. + /// + /// + public void SendCommandToPlugins(string[] args) + { + m_eventManager.TriggerOnPluginConsole(args); + } + + public LandData GetLandData(float x, float y) + { + return LandChannel.GetLandObject(x, y).LandData; + } + + /// + /// Get LandData by position. + /// + /// + /// + public LandData GetLandData(Vector3 pos) + { + return GetLandData(pos.X, pos.Y); + } + + public LandData GetLandData(uint x, uint y) + { + m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); + return LandChannel.GetLandObject((int)x, (int)y).LandData; + } + + #endregion + + #region Script Engine + + private bool ScriptDanger(SceneObjectPart part, Vector3 pos) + { + ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); + if (part != null) + { + if (parcel != null) + { + if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0) + { + return true; + } + else if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID)) + { + return true; + } + else if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0) + && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID)) + { + return true; + } + else + { + return false; + } } + else + { + if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY) + { + // The only time parcel != null when an object is inside a region is when + // there is nothing behind the landchannel. IE, no land plugin loaded. + return true; + } + else + { + // The object is outside of this region. Stop piping events to it. + return false; + } + } + } + else + { + return false; + } + } + + public bool ScriptDanger(uint localID, Vector3 pos) + { + SceneObjectPart part = GetSceneObjectPart(localID); + if (part != null) + { + return ScriptDanger(part, pos); + } + else + { + return false; + } + } + + public bool PipeEventsForScript(uint localID) + { + SceneObjectPart part = GetSceneObjectPart(localID); + + if (part != null) + { + SceneObjectPart parent = part.ParentGroup.RootPart; + return ScriptDanger(parent, parent.GetWorldPosition()); + } + else + { return false; - } - - /// - /// Tell a single client to prepare to close. - /// - /// - /// This should only be called if we may close the client but there will be some delay in so doing. Meant for - /// internal use - other callers should almost certainly called CloseClient(). - /// - /// - /// true if pre-close state notification was successful. false if the agent - /// was not in a state where it could transition to pre-close. - public bool IncomingPreCloseClient(ScenePresence sp) - { - lock (m_removeClientLock) - { - // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may - // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not - // want to obey this close since C may have renewed the child agent lease on B. - if (sp.DoNotCloseAfterTeleport) - { - m_log.DebugFormat( - "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection", - sp.IsChildAgent ? "child" : "root", sp.Name, Name); - - // Need to reset the flag so that a subsequent close after another teleport can succeed. - sp.DoNotCloseAfterTeleport = false; - - return false; - } - - if (sp.LifecycleState != ScenePresenceState.Running) - { - m_log.DebugFormat( - "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}", - sp.Name, Name, sp.LifecycleState); - - return false; - } - - sp.LifecycleState = ScenePresenceState.PreRemove; - - return true; - } - } - - /// - /// Tell a single agent to disconnect from the region. - /// - /// - /// - /// Force the agent to close even if it might be in the middle of some other operation. You do not want to - /// force unless you are absolutely sure that the agent is dead and a normal close is not working. - /// - public override bool CloseAgent(UUID agentID, bool force) - { - ScenePresence sp; - - lock (m_removeClientLock) - { - sp = GetScenePresence(agentID); - - if (sp == null) - { - m_log.DebugFormat( - "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", - agentID, Name); - - return false; - } - - if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove) - { - m_log.DebugFormat( - "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}", - sp.Name, Name, sp.LifecycleState); - - return false; - } - - // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may - // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not - // want to obey this close since C may have renewed the child agent lease on B. - if (sp.DoNotCloseAfterTeleport) - { - m_log.DebugFormat( - "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection", - sp.IsChildAgent ? "child" : "root", sp.Name, Name); - - // Need to reset the flag so that a subsequent close after another teleport can succeed. - sp.DoNotCloseAfterTeleport = false; - - return false; - } - - sp.LifecycleState = ScenePresenceState.Removing; - } - - sp.ControllingClient.Close(force); + } + } + + #endregion + + #region SceneGraph wrapper methods + + /// + /// + /// + /// + /// + public UUID ConvertLocalIDToFullID(uint localID) + { + return m_sceneGraph.ConvertLocalIDToFullID(localID); + } + + public void SwapRootAgentCount(bool rootChildChildRootTF) + { + m_sceneGraph.SwapRootChildAgent(rootChildChildRootTF); + } + + public void AddPhysicalPrim(int num) + { + m_sceneGraph.AddPhysicalPrim(num); + } + + public void RemovePhysicalPrim(int num) + { + m_sceneGraph.RemovePhysicalPrim(num); + } + + public int GetRootAgentCount() + { + return m_sceneGraph.GetRootAgentCount(); + } + + public int GetChildAgentCount() + { + return m_sceneGraph.GetChildAgentCount(); + } + + /// + /// Request a scene presence by UUID. Fast, indexed lookup. + /// + /// + /// null if the presence was not found + public ScenePresence GetScenePresence(UUID agentID) + { + return m_sceneGraph.GetScenePresence(agentID); + } + + /// + /// Request the scene presence by name. + /// + /// + /// + /// null if the presence was not found + public ScenePresence GetScenePresence(string firstName, string lastName) + { + return m_sceneGraph.GetScenePresence(firstName, lastName); + } + + /// + /// Request the scene presence by localID. + /// + /// + /// null if the presence was not found + public ScenePresence GetScenePresence(uint localID) + { + return m_sceneGraph.GetScenePresence(localID); + } + + /// + /// Gets all the scene presences in this scene. + /// + /// + /// This method will return both root and child scene presences. + /// + /// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not + /// involving creating a new List object. + /// + /// + /// A list of the scene presences. Adding or removing from the list will not affect the presences in the scene. + /// + public List GetScenePresences() + { + return new List(m_sceneGraph.GetScenePresences()); + } + + /// + /// Performs action on all avatars in the scene (root scene presences) + /// Avatars may be an NPC or a 'real' client. + /// + /// + public void ForEachRootScenePresence(Action action) + { + m_sceneGraph.ForEachAvatar(action); + } + + /// + /// Performs action on all scene presences (root and child) + /// + /// + public void ForEachScenePresence(Action action) + { + m_sceneGraph.ForEachScenePresence(action); + } + + /// + /// Get all the scene object groups. + /// + /// + /// The scene object groups. If the scene is empty then an empty list is returned. + /// + public List GetSceneObjectGroups() + { + return m_sceneGraph.GetSceneObjectGroups(); + } + + /// + /// Get a group via its UUID + /// + /// + /// null if no group with that id exists + public SceneObjectGroup GetSceneObjectGroup(UUID fullID) + { + return m_sceneGraph.GetSceneObjectGroup(fullID); + } + + /// + /// Get a group via its local ID + /// + /// This will only return a group if the local ID matches a root part + /// + /// null if no group with that id exists + public SceneObjectGroup GetSceneObjectGroup(uint localID) + { + return m_sceneGraph.GetSceneObjectGroup(localID); + } + + /// + /// Get a group by name from the scene (will return the first + /// found, if there are more than one prim with the same name) + /// + /// + /// null if no group with that name exists + public SceneObjectGroup GetSceneObjectGroup(string name) + { + return m_sceneGraph.GetSceneObjectGroup(name); + } + + /// + /// Attempt to get the SOG via its UUID + /// + /// + /// + /// + public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog) + { + sog = GetSceneObjectGroup(fullID); + return sog != null; + } + + /// + /// Get a prim by name from the scene (will return the first + /// found, if there are more than one prim with the same name) + /// + /// + /// + public SceneObjectPart GetSceneObjectPart(string name) + { + return m_sceneGraph.GetSceneObjectPart(name); + } + + /// + /// Get a prim via its local id + /// + /// + /// + public SceneObjectPart GetSceneObjectPart(uint localID) + { + return m_sceneGraph.GetSceneObjectPart(localID); + } + + /// + /// Get a prim via its UUID + /// + /// + /// + public SceneObjectPart GetSceneObjectPart(UUID fullID) + { + return m_sceneGraph.GetSceneObjectPart(fullID); + } + + /// + /// Attempt to get a prim via its UUID + /// + /// + /// + /// + public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop) + { + sop = GetSceneObjectPart(fullID); + return sop != null; + } + + /// + /// Get a scene object group that contains the prim with the given local id + /// + /// + /// null if no scene object group containing that prim is found + public SceneObjectGroup GetGroupByPrim(uint localID) + { + return m_sceneGraph.GetGroupByPrim(localID); + } + + /// + /// Get a scene object group that contains the prim with the given uuid + /// + /// + /// null if no scene object group containing that prim is found + public SceneObjectGroup GetGroupByPrim(UUID fullID) + { + return m_sceneGraph.GetGroupByPrim(fullID); + } + + public override bool TryGetScenePresence(UUID agentID, out ScenePresence sp) + { + return m_sceneGraph.TryGetScenePresence(agentID, out sp); + } + + public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) + { + return m_sceneGraph.TryGetAvatarByName(avatarName, out avatar); + } + + /// + /// Perform an action on all clients with an avatar in this scene (root only) + /// + /// + public void ForEachRootClient(Action action) + { + ForEachRootScenePresence(delegate(ScenePresence presence) + { + action(presence.ControllingClient); + }); + } + + /// + /// Perform an action on all clients connected to the region (root and child) + /// + /// + public void ForEachClient(Action action) + { + m_clientManager.ForEachSync(action); + } + + public bool TryGetClient(UUID avatarID, out IClientAPI client) + { + return m_clientManager.TryGetValue(avatarID, out client); + } + + public bool TryGetClient(System.Net.IPEndPoint remoteEndPoint, out IClientAPI client) + { + return m_clientManager.TryGetValue(remoteEndPoint, out client); + } + + public void ForEachSOG(Action action) + { + m_sceneGraph.ForEachSOG(action); + } + + /// + /// Returns a list of the entities in the scene. This is a new list so operations perform on the list itself + /// will not affect the original list of objects in the scene. + /// + /// + public EntityBase[] GetEntities() + { + return m_sceneGraph.GetEntities(); + } + + #endregion + + + // Commented pending deletion since this method no longer appears to do anything at all + // public bool NeedSceneCacheClear(UUID agentID) + // { + // IInventoryTransferModule inv = RequestModuleInterface(); + // if (inv == null) + // return true; + // + // return inv.NeedSceneCacheClear(agentID, this); + // } + + public void CleanTempObjects() + { + EntityBase[] entities = GetEntities(); + foreach (EntityBase obj in entities) + { + if (obj is SceneObjectGroup) + { + SceneObjectGroup grp = (SceneObjectGroup)obj; + + if (!grp.IsDeleted) + { + if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) + { + if (grp.RootPart.Expires <= DateTime.Now) + DeleteSceneObject(grp, false); + } + } + } + } + + } + + public void DeleteFromStorage(UUID uuid) + { + SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); + } + + public int GetHealth() + { + // Returns: + // 1 = sim is up and accepting http requests. The heartbeat has + // stopped and the sim is probably locked up, but a remote + // admin restart may succeed + // + // 2 = Sim is up and the heartbeat is running. The sim is likely + // usable for people within and logins _may_ work + // + // 3 = We have seen a new user enter within the past 4 minutes + // which can be seen as positive confirmation of sim health + // + int health = 1; // Start at 1, means we're up + + if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) + health += 1; + else + return health; - return true; - } - - /// - /// Tries to teleport agent to another region. - /// - /// - /// The region name must exactly match that given. - /// - /// - /// - /// - /// - /// - public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, - Vector3 lookat, uint teleportFlags) - { - GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName); - - if (region == null) - { - // can't find the region: Tell viewer and abort - remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); - return; - } - - RequestTeleportLocation(remoteClient, region.RegionHandle, position, lookat, teleportFlags); - } - - /// - /// Tries to teleport agent to other region. - /// - /// - /// - /// - /// - /// - public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, - Vector3 lookAt, uint teleportFlags) - { - ScenePresence sp = GetScenePresence(remoteClient.AgentId); - if (sp != null) - { - if (EntityTransferModule != null) - { - EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); - } - else - { - m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active"); - sp.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator."); - } - } - } + // A login in the last 4 mins? We can't be doing too badly + // + if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) + health++; + else + return health; - public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) - { - if (EntityTransferModule != null) - { - return EntityTransferModule.Cross(agent, isFlying); + // CheckHeartbeat(); + + return health; + } + + // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and + // update non-physical objects like the joint proxy objects that represent the position + // of the joints in the scene. + + // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene + // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called + // from within the OdePhysicsScene. + + protected internal void jointMoved(PhysicsJoint joint) + { + // m_parentScene.PhysicsScene.DumpJointInfo(); // non-thread-locked version; we should already be in a lock (OdeLock) when this callback is invoked + SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); + if (jointProxyObject == null) + { + jointErrorMessage(joint, "WARNING, joint proxy not found, name " + joint.ObjectNameInScene); + return; + } + + // now update the joint proxy object in the scene to have the position of the joint as returned by the physics engine + SceneObjectPart trackedBody = GetSceneObjectPart(joint.TrackedBodyName); // FIXME: causes a sequential lookup + if (trackedBody == null) return; // the actor may have been deleted but the joint still lingers around a few frames waiting for deletion. during this time, trackedBody is NULL to prevent further motion of the joint proxy. + jointProxyObject.Velocity = trackedBody.Velocity; + jointProxyObject.AngularVelocity = trackedBody.AngularVelocity; + switch (joint.Type) + { + case PhysicsJointType.Ball: + { + Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); + Vector3 proxyPos = jointAnchor; + jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update + } + break; + + case PhysicsJointType.Hinge: + { + Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); + + // Normally, we would just ask the physics scene to return the axis for the joint. + // Unfortunately, ODE sometimes returns <0,0,0> for the joint axis, which should + // never occur. Therefore we cannot rely on ODE to always return a correct joint axis. + // Therefore the following call does not always work: + //PhysicsVector phyJointAxis = _PhyScene.GetJointAxis(joint); + + // instead we compute the joint orientation by saving the original joint orientation + // relative to one of the jointed bodies, and applying this transformation + // to the current position of the jointed bodies (the tracked body) to compute the + // current joint orientation. + + if (joint.TrackedBodyName == null) + { + jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene); + } + + Vector3 proxyPos = jointAnchor; + Quaternion q = trackedBody.RotationOffset * joint.LocalRotation; + + jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update + jointProxyObject.ParentGroup.UpdateGroupRotationR(q); // schedules the entire group for a terse update + } + break; + } + } + + // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and + // update non-physical objects like the joint proxy objects that represent the position + // of the joints in the scene. + + // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene + // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called + // from within the OdePhysicsScene. + protected internal void jointDeactivated(PhysicsJoint joint) + { + //m_log.Debug("[NINJA] SceneGraph.jointDeactivated, joint:" + joint.ObjectNameInScene); + SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); + if (jointProxyObject == null) + { + jointErrorMessage(joint, "WARNING, trying to deactivate (stop interpolation of) joint proxy, but not found, name " + joint.ObjectNameInScene); + return; + } + + // turn the proxy non-physical, which also stops its client-side interpolation + bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); + if (wasUsingPhysics) + { + jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock + } + } + + // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and + // alert the user of errors by using the debug channel in the same way that scripts alert + // the user of compile errors. + + // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene + // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called + // from within the OdePhysicsScene. + public void jointErrorMessage(PhysicsJoint joint, string message) + { + if (joint != null) + { + if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages) + return; + + SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); + if (jointProxyObject != null) + { + SimChat(Utils.StringToBytes("[NINJA]: " + message), + ChatTypeEnum.DebugChannel, + 2147483647, + jointProxyObject.AbsolutePosition, + jointProxyObject.Name, + jointProxyObject.UUID, + false); + + joint.ErrorMessageCount++; + + if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages) + { + SimChat(Utils.StringToBytes("[NINJA]: Too many messages for this joint, suppressing further messages."), + ChatTypeEnum.DebugChannel, + 2147483647, + jointProxyObject.AbsolutePosition, + jointProxyObject.Name, + jointProxyObject.UUID, + false); + } } else { - m_log.DebugFormat("[SCENE]: Unable to cross agent to neighbouring region, because there is no AgentTransferModule"); + // couldn't find the joint proxy object; the error message is silently suppressed } + } + } - return false; - } - - public void SendOutChildAgentUpdates(AgentPosition cadu, ScenePresence presence) - { - m_sceneGridService.SendChildAgentDataUpdate(cadu, presence); - } - - #endregion - - #region Other Methods - - protected override IConfigSource GetConfig() - { - return m_config; - } - - #endregion - - public void HandleObjectPermissionsUpdate(IClientAPI controller, UUID agentID, UUID sessionID, byte field, uint localId, uint mask, byte set) - { - // Check for spoofing.. since this is permissions we're talking about here! - if ((controller.SessionId == sessionID) && (controller.AgentId == agentID)) - { - // Tell the object to do permission update - if (localId != 0) - { - SceneObjectGroup chObjectGroup = GetGroupByPrim(localId); - if (chObjectGroup != null) - { - chObjectGroup.UpdatePermissions(agentID, field, localId, mask, set); - } - } - } - } - - /// - /// Causes all clients to get a full object update on all of the objects in the scene. - /// - public void ForceClientUpdate() - { - EntityBase[] entityList = GetEntities(); - foreach (EntityBase ent in entityList) - { - if (ent is SceneObjectGroup) - { - ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); - } - } - } - - /// - /// This is currently only used for scale (to scale to MegaPrim size) - /// There is a console command that calls this in OpenSimMain - /// - /// - public void HandleEditCommand(string[] cmdparams) - { - m_log.DebugFormat("Searching for Primitive: '{0}'", cmdparams[2]); - - EntityBase[] entityList = GetEntities(); - foreach (EntityBase ent in entityList) - { - if (ent is SceneObjectGroup) - { - SceneObjectPart part = ((SceneObjectGroup)ent).GetPart(((SceneObjectGroup)ent).UUID); - if (part != null) - { - if (part.Name == cmdparams[2]) - { - part.Resize( - new Vector3(Convert.ToSingle(cmdparams[3]), Convert.ToSingle(cmdparams[4]), - Convert.ToSingle(cmdparams[5]))); - - m_log.DebugFormat("Edited scale of Primitive: {0}", part.Name); - } - } - } - } - } - - #region Script Handling Methods - - /// - /// Console command handler to send script command to script engine. - /// - /// - public void SendCommandToPlugins(string[] args) - { - m_eventManager.TriggerOnPluginConsole(args); - } - - public LandData GetLandData(float x, float y) - { - return LandChannel.GetLandObject(x, y).LandData; - } - - /// - /// Get LandData by position. - /// - /// - /// - public LandData GetLandData(Vector3 pos) - { - return GetLandData(pos.X, pos.Y); - } - - public LandData GetLandData(uint x, uint y) - { - m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); - return LandChannel.GetLandObject((int)x, (int)y).LandData; - } - - #endregion - - #region Script Engine - - private bool ScriptDanger(SceneObjectPart part,Vector3 pos) - { - ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); - if (part != null) - { - if (parcel != null) - { - if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0) - { - return true; - } - else if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID)) - { - return true; - } - else if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0) - && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID)) - { - return true; - } - else - { - return false; - } - } - else - { - - if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY) - { - // The only time parcel != null when an object is inside a region is when - // there is nothing behind the landchannel. IE, no land plugin loaded. - return true; - } - else - { - // The object is outside of this region. Stop piping events to it. - return false; - } - } + public Scene ConsoleScene() + { + if (MainConsole.Instance == null) + return null; + if (MainConsole.Instance.ConsoleScene is Scene) + return (Scene)MainConsole.Instance.ConsoleScene; + return null; + } + + // Get terrain height at the specified location. + // Presumes the underlying implementation is a heightmap which is a 1m grid. + // Finds heightmap grid points before and after the point and + // does a linear approximation of the height at this intermediate point. + public float GetGroundHeight(float x, float y) + { + if (x < 0) + x = 0; + if (x >= Heightmap.Width) + x = Heightmap.Width - 1; + if (y < 0) + y = 0; + if (y >= Heightmap.Height) + y = Heightmap.Height - 1; + + Vector3 p0 = new Vector3(x, y, (float)Heightmap[(int)x, (int)y]); + Vector3 p1 = p0; + Vector3 p2 = p0; + + p1.X += 1.0f; + if (p1.X < Heightmap.Width) + p1.Z = (float)Heightmap[(int)p1.X, (int)p1.Y]; + + p2.Y += 1.0f; + if (p2.Y < Heightmap.Height) + p2.Z = (float)Heightmap[(int)p2.X, (int)p2.Y]; + + Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); + Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z); + + v0.Normalize(); + v1.Normalize(); + + Vector3 vsn = new Vector3(); + vsn.X = (v0.Y * v1.Z) - (v0.Z * v1.Y); + vsn.Y = (v0.Z * v1.X) - (v0.X * v1.Z); + vsn.Z = (v0.X * v1.Y) - (v0.Y * v1.X); + vsn.Normalize(); + + float xdiff = x - (float)((int)x); + float ydiff = y - (float)((int)y); + + return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; + } + + // private void CheckHeartbeat() + // { + // if (m_firstHeartbeat) + // return; + // + // if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) + // StartTimer(); + // } + + public override ISceneObject DeserializeObject(string representation) + { + return SceneObjectSerializer.FromXml2Format(representation); + } + + public override bool AllowScriptCrossings + { + get { return m_allowScriptCrossings; } + } + + public Vector3 GetNearestAllowedPosition(ScenePresence avatar) + { + return GetNearestAllowedPosition(avatar, null); + } + + public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel) + { + ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel); + + if (nearestParcel != null) + { + Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1)); + //Try to get a location that feels like where they came from + Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); + if (nearestPoint != null) + { + m_log.Debug("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString()); + return nearestPoint.Value; + } + + //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel + Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition); + dir = Vector3.Normalize(directionToParcelCenter); + nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); + if (nearestPoint != null) + { + m_log.Debug("They had a zero velocity, sending them to: " + nearestPoint.ToString()); + return nearestPoint.Value; + } + + ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y); + if (dest != excludeParcel) + { + // Ultimate backup if we have no idea where they are and + // the last allowed position was in another parcel + m_log.Debug("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString()); + return avatar.lastKnownAllowedPosition; + } + + // else fall through to region edge + } + + //Go to the edge, this happens in teleporting to a region with no available parcels + Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); + + //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); + + return nearestRegionEdgePoint; + } + + private Vector3 GetParcelCenterAtGround(ILandObject parcel) + { + Vector2 center = GetParcelCenter(parcel); + return GetPositionAtGround(center.X, center.Y); + } + + private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel) + { + Vector3 unitDirection = Vector3.Normalize(direction); + //Making distance to search go through some sane limit of distance + for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f) + { + Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); + if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) + { + return testPos; + } + } + return null; + } + + public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) + { + return GetNearestAllowedParcel(avatarId, x, y, null); + } + + public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel) + { + List all = AllParcels(); + float minParcelDistance = float.MaxValue; + ILandObject nearestParcel = null; + + foreach (var parcel in all) + { + if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel) + { + float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); + if (parcelDistance < minParcelDistance) + { + minParcelDistance = parcelDistance; + nearestParcel = parcel; + } + } + } + + return nearestParcel; + } + + private List AllParcels() + { + return LandChannel.AllParcels(); + } + + private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y) + { + return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel)); + } + + //calculate the average center point of a parcel + private Vector2 GetParcelCenter(ILandObject parcel) + { + int count = 0; + int avgx = 0; + int avgy = 0; + for (int x = 0; x < RegionInfo.RegionSizeX; x++) + { + for (int y = 0; y < RegionInfo.RegionSizeY; y++) + { + //Just keep a running average as we check if all the points are inside or not + if (parcel.ContainsPoint(x, y)) + { + if (count == 0) + { + avgx = x; + avgy = y; + } + else + { + avgx = (avgx * count + x) / (count + 1); + avgy = (avgy * count + y) / (count + 1); + } + count += 1; + } + } + } + return new Vector2(avgx, avgy); + } + + private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) + { + float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2 + ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X; + float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2 + ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y; + + //find out what vertical edge to go to + if (xdistance < ydistance) + { + if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2) + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); } else { - return false; + return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y); } - } - - public bool ScriptDanger(uint localID, Vector3 pos) - { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null) + } + //find out what horizontal edge to go to + else + { + if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2) { - return ScriptDanger(part, pos); + return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); } else { - return false; - } - } + return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY); + } + } + } + + private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y) + { + Vector3 ground = GetPositionAtGround(x, y); + if (avatar.AbsolutePosition.Z > ground.Z) + { + ground.Z = avatar.AbsolutePosition.Z; + } + return ground; + } + + private Vector3 GetPositionAtGround(float x, float y) + { + return new Vector3(x, y, GetGroundHeight(x, y)); + } + + public List GetEstateRegions(int estateID) + { + IEstateDataService estateDataService = EstateDataService; + if (estateDataService == null) + return new List(0); + + return estateDataService.GetRegions(estateID); + } + + public void ReloadEstateData() + { + IEstateDataService estateDataService = EstateDataService; + if (estateDataService != null) + { + RegionInfo.EstateSettings = estateDataService.LoadEstateSettings(RegionInfo.RegionID, false); + TriggerEstateSunUpdate(); + } + } + + public void TriggerEstateSunUpdate() + { + EventManager.TriggerEstateToolsSunUpdate(RegionInfo.RegionHandle); + } + + private void HandleReloadEstate(string module, string[] cmd) + { + if (MainConsole.Instance.ConsoleScene == null || + (MainConsole.Instance.ConsoleScene is Scene && + (Scene)MainConsole.Instance.ConsoleScene == this)) + { + ReloadEstateData(); + } + } + + /// + /// Get the volume of space that will encompass all the given objects. + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static Vector3[] GetCombinedBoundingBox( + List objects, + out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) + { + minX = float.MaxValue; + maxX = float.MinValue; + minY = float.MaxValue; + maxY = float.MinValue; + minZ = float.MaxValue; + maxZ = float.MinValue; + + List offsets = new List(); + + foreach (SceneObjectGroup g in objects) + { + float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; + + Vector3 vec = g.AbsolutePosition; + + g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); + + // m_log.DebugFormat( + // "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}", + // g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ)); + + ominX += vec.X; + omaxX += vec.X; + ominY += vec.Y; + omaxY += vec.Y; + ominZ += vec.Z; + omaxZ += vec.Z; + + if (minX > ominX) + minX = ominX; + if (minY > ominY) + minY = ominY; + if (minZ > ominZ) + minZ = ominZ; + if (maxX < omaxX) + maxX = omaxX; + if (maxY < omaxY) + maxY = omaxY; + if (maxZ < omaxZ) + maxZ = omaxZ; + } + + foreach (SceneObjectGroup g in objects) + { + Vector3 vec = g.AbsolutePosition; + vec.X -= minX; + vec.Y -= minY; + vec.Z -= minZ; + + offsets.Add(vec); + } + + return offsets.ToArray(); + } + + /// + /// Regenerate the maptile for this scene. + /// + /// + /// + private void RegenerateMaptile() + { + IWorldMapModule mapModule = RequestModuleInterface(); + if (mapModule != null) + mapModule.GenerateMaptile(); + } + + private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) + { + RegenerateMaptile(); + + // We need to propagate the new image UUID to the grid service + // so that all simulators can retrieve it + string error = GridService.RegisterRegion(RegionInfo.ScopeID, new GridRegion(RegionInfo)); + if (error != string.Empty) + throw new Exception(error); + } + + /// + /// This method is called across the simulation connector to + /// determine if a given agent is allowed in this region + /// AS A ROOT AGENT + /// + /// + /// Returning false here will prevent them + /// from logging into the region, teleporting into the region + /// or corssing the broder walking, but will NOT prevent + /// child agent creation, thereby emulating the SL behavior. + /// + /// The visitor's User ID + /// The visitor's Home URI (may be null) + /// + /// + /// + public bool QueryAccess(UUID agentID, string agentHomeURI, bool viaTeleport, Vector3 position, out string reason) + { + reason = string.Empty; + + if (Permissions.IsGod(agentID)) + { + reason = String.Empty; + return true; + } - public bool PipeEventsForScript(uint localID) - { - SceneObjectPart part = GetSceneObjectPart(localID); + if (!AllowAvatarCrossing && !viaTeleport) + return false; + + // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. + // However, the long term fix is to make sure root agent count is always accurate. + m_sceneGraph.RecalculateStats(); - if (part != null) + int num = m_sceneGraph.GetRootAgentCount(); + + if (num >= RegionInfo.RegionSettings.AgentLimit) + { + if (!Permissions.IsAdministrator(agentID)) { - SceneObjectPart parent = part.ParentGroup.RootPart; - return ScriptDanger(parent, parent.GetWorldPosition()); + reason = "The region is full"; + + m_log.DebugFormat( + "[SCENE]: Denying presence with id {0} entry into {1} since region is at agent limit of {2}", + agentID, RegionInfo.RegionName, RegionInfo.RegionSettings.AgentLimit); + + return false; } - else - { - return false; - } - } - - #endregion - - #region SceneGraph wrapper methods - - /// - /// - /// - /// - /// - public UUID ConvertLocalIDToFullID(uint localID) - { - return m_sceneGraph.ConvertLocalIDToFullID(localID); - } - - public void SwapRootAgentCount(bool rootChildChildRootTF) - { - m_sceneGraph.SwapRootChildAgent(rootChildChildRootTF); - } - - public void AddPhysicalPrim(int num) - { - m_sceneGraph.AddPhysicalPrim(num); - } - - public void RemovePhysicalPrim(int num) - { - m_sceneGraph.RemovePhysicalPrim(num); - } - - public int GetRootAgentCount() - { - return m_sceneGraph.GetRootAgentCount(); - } - - public int GetChildAgentCount() - { - return m_sceneGraph.GetChildAgentCount(); - } - - /// - /// Request a scene presence by UUID. Fast, indexed lookup. - /// - /// - /// null if the presence was not found - public ScenePresence GetScenePresence(UUID agentID) - { - return m_sceneGraph.GetScenePresence(agentID); - } - - /// - /// Request the scene presence by name. - /// - /// - /// - /// null if the presence was not found - public ScenePresence GetScenePresence(string firstName, string lastName) - { - return m_sceneGraph.GetScenePresence(firstName, lastName); - } - - /// - /// Request the scene presence by localID. - /// - /// - /// null if the presence was not found - public ScenePresence GetScenePresence(uint localID) - { - return m_sceneGraph.GetScenePresence(localID); - } - - /// - /// Gets all the scene presences in this scene. - /// - /// - /// This method will return both root and child scene presences. - /// - /// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not - /// involving creating a new List object. - /// - /// - /// A list of the scene presences. Adding or removing from the list will not affect the presences in the scene. - /// - public List GetScenePresences() - { - return new List(m_sceneGraph.GetScenePresences()); - } - - /// - /// Performs action on all avatars in the scene (root scene presences) - /// Avatars may be an NPC or a 'real' client. - /// - /// - public void ForEachRootScenePresence(Action action) - { - m_sceneGraph.ForEachAvatar(action); - } - - /// - /// Performs action on all scene presences (root and child) - /// - /// - public void ForEachScenePresence(Action action) - { - m_sceneGraph.ForEachScenePresence(action); - } - - /// - /// Get all the scene object groups. - /// - /// - /// The scene object groups. If the scene is empty then an empty list is returned. - /// - public List GetSceneObjectGroups() - { - return m_sceneGraph.GetSceneObjectGroups(); - } - - /// - /// Get a group via its UUID - /// - /// - /// null if no group with that id exists - public SceneObjectGroup GetSceneObjectGroup(UUID fullID) - { - return m_sceneGraph.GetSceneObjectGroup(fullID); - } - - /// - /// Get a group via its local ID - /// - /// This will only return a group if the local ID matches a root part - /// - /// null if no group with that id exists - public SceneObjectGroup GetSceneObjectGroup(uint localID) - { - return m_sceneGraph.GetSceneObjectGroup(localID); - } - - /// - /// Get a group by name from the scene (will return the first - /// found, if there are more than one prim with the same name) - /// - /// - /// null if no group with that name exists - public SceneObjectGroup GetSceneObjectGroup(string name) - { - return m_sceneGraph.GetSceneObjectGroup(name); - } - - /// - /// Attempt to get the SOG via its UUID - /// - /// - /// - /// - public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog) - { - sog = GetSceneObjectGroup(fullID); - return sog != null; - } - - /// - /// Get a prim by name from the scene (will return the first - /// found, if there are more than one prim with the same name) - /// - /// - /// - public SceneObjectPart GetSceneObjectPart(string name) - { - return m_sceneGraph.GetSceneObjectPart(name); - } - - /// - /// Get a prim via its local id - /// - /// - /// - public SceneObjectPart GetSceneObjectPart(uint localID) - { - return m_sceneGraph.GetSceneObjectPart(localID); - } - - /// - /// Get a prim via its UUID - /// - /// - /// - public SceneObjectPart GetSceneObjectPart(UUID fullID) - { - return m_sceneGraph.GetSceneObjectPart(fullID); - } - - /// - /// Attempt to get a prim via its UUID - /// - /// - /// - /// - public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop) - { - sop = GetSceneObjectPart(fullID); - return sop != null; - } - - /// - /// Get a scene object group that contains the prim with the given local id - /// - /// - /// null if no scene object group containing that prim is found - public SceneObjectGroup GetGroupByPrim(uint localID) - { - return m_sceneGraph.GetGroupByPrim(localID); - } - - /// - /// Get a scene object group that contains the prim with the given uuid - /// - /// - /// null if no scene object group containing that prim is found - public SceneObjectGroup GetGroupByPrim(UUID fullID) - { - return m_sceneGraph.GetGroupByPrim(fullID); - } - - public override bool TryGetScenePresence(UUID agentID, out ScenePresence sp) - { - return m_sceneGraph.TryGetScenePresence(agentID, out sp); - } - - public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) - { - return m_sceneGraph.TryGetAvatarByName(avatarName, out avatar); - } - - /// - /// Perform an action on all clients with an avatar in this scene (root only) - /// - /// - public void ForEachRootClient(Action action) - { - ForEachRootScenePresence(delegate(ScenePresence presence) - { - action(presence.ControllingClient); - }); - } - - /// - /// Perform an action on all clients connected to the region (root and child) - /// - /// - public void ForEachClient(Action action) - { - m_clientManager.ForEachSync(action); - } - - public bool TryGetClient(UUID avatarID, out IClientAPI client) - { - return m_clientManager.TryGetValue(avatarID, out client); - } - - public bool TryGetClient(System.Net.IPEndPoint remoteEndPoint, out IClientAPI client) - { - return m_clientManager.TryGetValue(remoteEndPoint, out client); - } - - public void ForEachSOG(Action action) - { - m_sceneGraph.ForEachSOG(action); - } - - /// - /// Returns a list of the entities in the scene. This is a new list so operations perform on the list itself - /// will not affect the original list of objects in the scene. - /// - /// - public EntityBase[] GetEntities() - { - return m_sceneGraph.GetEntities(); - } - - #endregion - - -// Commented pending deletion since this method no longer appears to do anything at all -// public bool NeedSceneCacheClear(UUID agentID) -// { -// IInventoryTransferModule inv = RequestModuleInterface(); -// if (inv == null) -// return true; -// -// return inv.NeedSceneCacheClear(agentID, this); -// } - - public void CleanTempObjects() - { - EntityBase[] entities = GetEntities(); - foreach (EntityBase obj in entities) - { - if (obj is SceneObjectGroup) - { - SceneObjectGroup grp = (SceneObjectGroup)obj; - - if (!grp.IsDeleted) - { - if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) - { - if (grp.RootPart.Expires <= DateTime.Now) - DeleteSceneObject(grp, false); - } - } - } - } - - } - - public void DeleteFromStorage(UUID uuid) - { - SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); - } - - public int GetHealth() - { - // Returns: - // 1 = sim is up and accepting http requests. The heartbeat has - // stopped and the sim is probably locked up, but a remote - // admin restart may succeed - // - // 2 = Sim is up and the heartbeat is running. The sim is likely - // usable for people within and logins _may_ work - // - // 3 = We have seen a new user enter within the past 4 minutes - // which can be seen as positive confirmation of sim health - // - int health=1; // Start at 1, means we're up + } - if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) - health += 1; - else - return health; + ScenePresence presence = GetScenePresence(agentID); + IClientAPI client = null; + AgentCircuitData aCircuit = null; - // A login in the last 4 mins? We can't be doing too badly - // - if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) - health++; - else - return health; + if (presence != null) + { + client = presence.ControllingClient; + if (client != null) + aCircuit = client.RequestClientInfo(); + } -// CheckHeartbeat(); + // We may be called before there is a presence or a client. + // Fake AgentCircuitData to keep IAuthorizationModule smiling + if (client == null) + { + aCircuit = new AgentCircuitData(); + aCircuit.AgentID = agentID; + aCircuit.firstname = String.Empty; + aCircuit.lastname = String.Empty; + } - return health; - } + try + { + if (!AuthorizeUser(aCircuit, false, out reason)) + { + //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); + return false; + } + } + catch (Exception e) + { + m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} " + e.StackTrace, e.Message); + reason = "Error authorizing agent: " + e.Message; + return false; + } + + if (viaTeleport) + { + if (!RegionInfo.EstateSettings.AllowDirectTeleport) + { + SceneObjectGroup telehub; + if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject)) != null) + { + List spawnPoints = RegionInfo.RegionSettings.SpawnPoints(); + bool banned = true; + foreach (SpawnPoint sp in spawnPoints) + { + Vector3 spawnPoint = sp.GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + ILandObject land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); + if (land == null) + continue; + if (land.IsEitherBannedOrRestricted(agentID)) + continue; + banned = false; + break; + } + + if (banned) + { + if (Permissions.IsAdministrator(agentID) == false || Permissions.IsGridGod(agentID) == false) + { + reason = "No suitable landing point found"; + return false; + } + reason = "Administrative access only"; + return true; + } + } + } - // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and - // update non-physical objects like the joint proxy objects that represent the position - // of the joints in the scene. + float posX = 128.0f; + float posY = 128.0f; - // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene - // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called - // from within the OdePhysicsScene. + if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY)) + { + // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID); + reason = "You are banned from the region on all parcels"; + return false; + } + } + else // Walking + { + ILandObject land = LandChannel.GetLandObject(position.X, position.Y); + if (land == null) + { + reason = "No parcel found"; + return false; + } - protected internal void jointMoved(PhysicsJoint joint) - { - // m_parentScene.PhysicsScene.DumpJointInfo(); // non-thread-locked version; we should already be in a lock (OdeLock) when this callback is invoked - SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); - if (jointProxyObject == null) - { - jointErrorMessage(joint, "WARNING, joint proxy not found, name " + joint.ObjectNameInScene); - return; - } - - // now update the joint proxy object in the scene to have the position of the joint as returned by the physics engine - SceneObjectPart trackedBody = GetSceneObjectPart(joint.TrackedBodyName); // FIXME: causes a sequential lookup - if (trackedBody == null) return; // the actor may have been deleted but the joint still lingers around a few frames waiting for deletion. during this time, trackedBody is NULL to prevent further motion of the joint proxy. - jointProxyObject.Velocity = trackedBody.Velocity; - jointProxyObject.AngularVelocity = trackedBody.AngularVelocity; - switch (joint.Type) - { - case PhysicsJointType.Ball: - { - Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); - Vector3 proxyPos = jointAnchor; - jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update - } - break; - - case PhysicsJointType.Hinge: - { - Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); - - // Normally, we would just ask the physics scene to return the axis for the joint. - // Unfortunately, ODE sometimes returns <0,0,0> for the joint axis, which should - // never occur. Therefore we cannot rely on ODE to always return a correct joint axis. - // Therefore the following call does not always work: - //PhysicsVector phyJointAxis = _PhyScene.GetJointAxis(joint); - - // instead we compute the joint orientation by saving the original joint orientation - // relative to one of the jointed bodies, and applying this transformation - // to the current position of the jointed bodies (the tracked body) to compute the - // current joint orientation. - - if (joint.TrackedBodyName == null) - { - jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene); - } - - Vector3 proxyPos = jointAnchor; - Quaternion q = trackedBody.RotationOffset * joint.LocalRotation; - - jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update - jointProxyObject.ParentGroup.UpdateGroupRotationR(q); // schedules the entire group for a terse update - } - break; - } - } - - // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and - // update non-physical objects like the joint proxy objects that represent the position - // of the joints in the scene. - - // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene - // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called - // from within the OdePhysicsScene. - protected internal void jointDeactivated(PhysicsJoint joint) - { - //m_log.Debug("[NINJA] SceneGraph.jointDeactivated, joint:" + joint.ObjectNameInScene); - SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); - if (jointProxyObject == null) - { - jointErrorMessage(joint, "WARNING, trying to deactivate (stop interpolation of) joint proxy, but not found, name " + joint.ObjectNameInScene); - return; - } - - // turn the proxy non-physical, which also stops its client-side interpolation - bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); - if (wasUsingPhysics) - { - jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock - } - } - - // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and - // alert the user of errors by using the debug channel in the same way that scripts alert - // the user of compile errors. - - // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene - // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called - // from within the OdePhysicsScene. - public void jointErrorMessage(PhysicsJoint joint, string message) - { - if (joint != null) - { - if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages) - return; - - SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); - if (jointProxyObject != null) - { - SimChat(Utils.StringToBytes("[NINJA]: " + message), - ChatTypeEnum.DebugChannel, - 2147483647, - jointProxyObject.AbsolutePosition, - jointProxyObject.Name, - jointProxyObject.UUID, - false); - - joint.ErrorMessageCount++; - - if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages) - { - SimChat(Utils.StringToBytes("[NINJA]: Too many messages for this joint, suppressing further messages."), - ChatTypeEnum.DebugChannel, - 2147483647, - jointProxyObject.AbsolutePosition, - jointProxyObject.Name, - jointProxyObject.UUID, - false); - } - } - else - { - // couldn't find the joint proxy object; the error message is silently suppressed - } - } - } - - public Scene ConsoleScene() - { - if (MainConsole.Instance == null) - return null; - if (MainConsole.Instance.ConsoleScene is Scene) - return (Scene)MainConsole.Instance.ConsoleScene; - return null; - } - - // Get terrain height at the specified location. - // Presumes the underlying implementation is a heightmap which is a 1m grid. - // Finds heightmap grid points before and after the point and - // does a linear approximation of the height at this intermediate point. - public float GetGroundHeight(float x, float y) - { - if (x < 0) - x = 0; - if (x >= Heightmap.Width) - x = Heightmap.Width - 1; - if (y < 0) - y = 0; - if (y >= Heightmap.Height) - y = Heightmap.Height - 1; - - Vector3 p0 = new Vector3(x, y, (float)Heightmap[(int)x, (int)y]); - Vector3 p1 = p0; - Vector3 p2 = p0; - - p1.X += 1.0f; - if (p1.X < Heightmap.Width) - p1.Z = (float)Heightmap[(int)p1.X, (int)p1.Y]; - - p2.Y += 1.0f; - if (p2.Y < Heightmap.Height) - p2.Z = (float)Heightmap[(int)p2.X, (int)p2.Y]; - - Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); - Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z); - - v0.Normalize(); - v1.Normalize(); - - Vector3 vsn = new Vector3(); - vsn.X = (v0.Y * v1.Z) - (v0.Z * v1.Y); - vsn.Y = (v0.Z * v1.X) - (v0.X * v1.Z); - vsn.Z = (v0.X * v1.Y) - (v0.Y * v1.X); - vsn.Normalize(); - - float xdiff = x - (float)((int)x); - float ydiff = y - (float)((int)y); - - return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; - } - -// private void CheckHeartbeat() -// { -// if (m_firstHeartbeat) -// return; -// -// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) -// StartTimer(); -// } - - public override ISceneObject DeserializeObject(string representation) - { - return SceneObjectSerializer.FromXml2Format(representation); - } - - public override bool AllowScriptCrossings - { - get { return m_allowScriptCrossings; } - } - - public Vector3 GetNearestAllowedPosition(ScenePresence avatar) - { - return GetNearestAllowedPosition(avatar, null); - } - - public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel) - { - ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel); + bool banned = land.IsBannedFromLand(agentID); + bool restricted = land.IsRestrictedFromLand(agentID); - if (nearestParcel != null) + if (banned || restricted) { - Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1)); - //Try to get a location that feels like where they came from - Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); - if (nearestPoint != null) - { - m_log.Debug("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString()); - return nearestPoint.Value; - } - - //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel - Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition); - dir = Vector3.Normalize(directionToParcelCenter); - nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); - if (nearestPoint != null) - { - m_log.Debug("They had a zero velocity, sending them to: " + nearestPoint.ToString()); - return nearestPoint.Value; - } - - ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y); - if (dest != excludeParcel) - { - // Ultimate backup if we have no idea where they are and - // the last allowed position was in another parcel - m_log.Debug("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString()); - return avatar.lastKnownAllowedPosition; - } - - // else fall through to region edge - } - - //Go to the edge, this happens in teleporting to a region with no available parcels - Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); - - //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); - - return nearestRegionEdgePoint; - } - - private Vector3 GetParcelCenterAtGround(ILandObject parcel) - { - Vector2 center = GetParcelCenter(parcel); - return GetPositionAtGround(center.X, center.Y); - } - - private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel) - { - Vector3 unitDirection = Vector3.Normalize(direction); - //Making distance to search go through some sane limit of distance - for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f) - { - Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); - if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) - { - return testPos; - } + if (banned) + reason = "You are banned from the parcel"; + else + reason = "The parcel is restricted"; + return false; + } + } + + reason = String.Empty; + return true; + } + + /// + /// This method deals with movement when an avatar is automatically moving (but this is distinct from the + /// autopilot that moves an avatar to a sit target!. + /// + /// + /// This is not intended as a permament location for this method. + /// + /// + private void HandleOnSignificantClientMovement(ScenePresence presence) + { + if (presence.MovingToTarget) + { + double distanceToTarget = Util.GetDistanceTo(presence.AbsolutePosition, presence.MoveToPositionTarget); + // m_log.DebugFormat( + // "[SCENE]: Abs pos of {0} is {1}, target {2}, distance {3}", + // presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget, distanceToTarget); + + // Check the error term of the current position in relation to the target position + if (distanceToTarget <= ScenePresence.SIGNIFICANT_MOVEMENT) + { + // We are close enough to the target + // m_log.DebugFormat("[SCENEE]: Stopping autopilot of {0}", presence.Name); + + presence.Velocity = Vector3.Zero; + presence.AbsolutePosition = presence.MoveToPositionTarget; + presence.ResetMoveToTarget(); + + if (presence.Flying) + { + // A horrible hack to stop the avatar dead in its tracks rather than having them overshoot + // the target if flying. + // We really need to be more subtle (slow the avatar as it approaches the target) or at + // least be able to set collision status once, rather than 5 times to give it enough + // weighting so that that PhysicsActor thinks it really is colliding. + for (int i = 0; i < 5; i++) + presence.IsColliding = true; + + if (presence.LandAtTarget) + presence.Flying = false; + + // Vector3 targetPos = presence.MoveToPositionTarget; + // float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y]; + // if (targetPos.Z - terrainHeight < 0.2) + // { + // presence.Flying = false; + // } + } + + // m_log.DebugFormat( + // "[SCENE]: AgentControlFlags {0}, MovementFlag {1} for {2}", + // presence.AgentControlFlags, presence.MovementFlag, presence.Name); } - return null; - } - - public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) - { - return GetNearestAllowedParcel(avatarId, x, y, null); - } - - public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel) - { - List all = AllParcels(); - float minParcelDistance = float.MaxValue; - ILandObject nearestParcel = null; - - foreach (var parcel in all) - { - if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel) - { - float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); - if (parcelDistance < minParcelDistance) - { - minParcelDistance = parcelDistance; - nearestParcel = parcel; - } - } - } - - return nearestParcel; - } - - private List AllParcels() - { - return LandChannel.AllParcels(); - } - - private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y) - { - return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel)); - } - - //calculate the average center point of a parcel - private Vector2 GetParcelCenter(ILandObject parcel) - { - int count = 0; - int avgx = 0; - int avgy = 0; - for (int x = 0; x < RegionInfo.RegionSizeX; x++) - { - for (int y = 0; y < RegionInfo.RegionSizeY; y++) - { - //Just keep a running average as we check if all the points are inside or not - if (parcel.ContainsPoint(x, y)) - { - if (count == 0) - { - avgx = x; - avgy = y; - } - else - { - avgx = (avgx * count + x) / (count + 1); - avgy = (avgy * count + y) / (count + 1); - } - count += 1; - } - } - } - return new Vector2(avgx, avgy); - } - - private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) - { - float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2 - ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X; - float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2 - ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y; - - //find out what vertical edge to go to - if (xdistance < ydistance) - { - if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2) - { - return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); - } - else - { - return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y); - } - } - //find out what horizontal edge to go to else { - if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2) - { - return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); - } - else - { - return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY); - } - } - } - - private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y) - { - Vector3 ground = GetPositionAtGround(x, y); - if (avatar.AbsolutePosition.Z > ground.Z) - { - ground.Z = avatar.AbsolutePosition.Z; - } - return ground; - } - - private Vector3 GetPositionAtGround(float x, float y) - { - return new Vector3(x, y, GetGroundHeight(x, y)); - } - - public List GetEstateRegions(int estateID) - { - IEstateDataService estateDataService = EstateDataService; - if (estateDataService == null) - return new List(0); - - return estateDataService.GetRegions(estateID); - } - - public void ReloadEstateData() - { - IEstateDataService estateDataService = EstateDataService; - if (estateDataService != null) - { - RegionInfo.EstateSettings = estateDataService.LoadEstateSettings(RegionInfo.RegionID, false); - TriggerEstateSunUpdate(); - } - } - - public void TriggerEstateSunUpdate() - { - EventManager.TriggerEstateToolsSunUpdate(RegionInfo.RegionHandle); - } - - private void HandleReloadEstate(string module, string[] cmd) - { - if (MainConsole.Instance.ConsoleScene == null || - (MainConsole.Instance.ConsoleScene is Scene && - (Scene)MainConsole.Instance.ConsoleScene == this)) - { - ReloadEstateData(); - } - } - - /// - /// Get the volume of space that will encompass all the given objects. - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static Vector3[] GetCombinedBoundingBox( - List objects, - out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) - { - minX = float.MaxValue; - maxX = float.MinValue; - minY = float.MaxValue; - maxY = float.MinValue; - minZ = float.MaxValue; - maxZ = float.MinValue; - - List offsets = new List(); - - foreach (SceneObjectGroup g in objects) - { - float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; - - Vector3 vec = g.AbsolutePosition; - - g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); - -// m_log.DebugFormat( -// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}", -// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ)); - - ominX += vec.X; - omaxX += vec.X; - ominY += vec.Y; - omaxY += vec.Y; - ominZ += vec.Z; - omaxZ += vec.Z; - - if (minX > ominX) - minX = ominX; - if (minY > ominY) - minY = ominY; - if (minZ > ominZ) - minZ = ominZ; - if (maxX < omaxX) - maxX = omaxX; - if (maxY < omaxY) - maxY = omaxY; - if (maxZ < omaxZ) - maxZ = omaxZ; - } - - foreach (SceneObjectGroup g in objects) - { - Vector3 vec = g.AbsolutePosition; - vec.X -= minX; - vec.Y -= minY; - vec.Z -= minZ; - - offsets.Add(vec); - } - - return offsets.ToArray(); - } - - /// - /// Regenerate the maptile for this scene. - /// - /// - /// - private void RegenerateMaptile() - { - IWorldMapModule mapModule = RequestModuleInterface(); - if (mapModule != null) - mapModule.GenerateMaptile(); - } - - private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) - { - RegenerateMaptile(); + // m_log.DebugFormat( + // "[SCENE]: Updating npc {0} at {1} for next movement to {2}", + // presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget); - // We need to propagate the new image UUID to the grid service - // so that all simulators can retrieve it - string error = GridService.RegisterRegion(RegionInfo.ScopeID, new GridRegion(RegionInfo)); - if (error != string.Empty) - throw new Exception(error); - } + Vector3 agent_control_v3 = new Vector3(); + presence.HandleMoveToTargetUpdate(1, ref agent_control_v3); + presence.AddNewMovement(agent_control_v3); + } + } + } - /// - /// This method is called across the simulation connector to - /// determine if a given agent is allowed in this region - /// AS A ROOT AGENT - /// - /// - /// Returning false here will prevent them - /// from logging into the region, teleporting into the region - /// or corssing the broder walking, but will NOT prevent - /// child agent creation, thereby emulating the SL behavior. - /// - /// The visitor's User ID - /// The visitor's Home URI (may be null) - /// - /// - /// - public bool QueryAccess(UUID agentID, string agentHomeURI, bool viaTeleport, Vector3 position, out string reason) - { - reason = string.Empty; + // manage and select spawn points in sequence + public int SpawnPoint() + { + int spawnpoints = RegionInfo.RegionSettings.SpawnPoints().Count; - if (Permissions.IsGod(agentID)) - { - reason = String.Empty; - return true; - } + if (spawnpoints == 0) + return 0; - if (!AllowAvatarCrossing && !viaTeleport) - return false; + m_SpawnPoint++; + if (m_SpawnPoint > spawnpoints) + m_SpawnPoint = 1; + return m_SpawnPoint - 1; + } - // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. - // However, the long term fix is to make sure root agent count is always accurate. - m_sceneGraph.RecalculateStats(); + /// + /// Wrappers to get physics modules retrieve assets. + /// + /// + /// Has to be done this way + /// because we can't assign the asset service to physics directly - at the + /// time physics are instantiated it's not registered but it will be by + /// the time the first prim exists. + /// + /// + /// + public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback) + { + AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived); + } - int num = m_sceneGraph.GetRootAgentCount(); + private void PhysicsAssetReceived(string id, Object sender, AssetBase asset) + { + AssetReceivedDelegate callback = (AssetReceivedDelegate)sender; - if (num >= RegionInfo.RegionSettings.AgentLimit) - { - if (!Permissions.IsAdministrator(agentID)) - { - reason = "The region is full"; + callback(asset); + } - m_log.DebugFormat( - "[SCENE]: Denying presence with id {0} entry into {1} since region is at agent limit of {2}", - agentID, RegionInfo.RegionName, RegionInfo.RegionSettings.AgentLimit); + public string GetExtraSetting(string name) + { + if (m_extraSettings == null) + return String.Empty; - return false; - } - } + string val; - ScenePresence presence = GetScenePresence(agentID); - IClientAPI client = null; - AgentCircuitData aCircuit = null; + if (!m_extraSettings.TryGetValue(name, out val)) + return String.Empty; - if (presence != null) - { - client = presence.ControllingClient; - if (client != null) - aCircuit = client.RequestClientInfo(); - } + return val; + } - // We may be called before there is a presence or a client. - // Fake AgentCircuitData to keep IAuthorizationModule smiling - if (client == null) - { - aCircuit = new AgentCircuitData(); - aCircuit.AgentID = agentID; - aCircuit.firstname = String.Empty; - aCircuit.lastname = String.Empty; - } + public void StoreExtraSetting(string name, string val) + { + if (m_extraSettings == null) + return; - try - { - if (!AuthorizeUser(aCircuit, false, out reason)) - { - //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); - return false; - } - } - catch (Exception e) - { - m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message); - reason = "Error authorizing agent: " + e.Message; - return false; - } - - if (viaTeleport) - { - if (!RegionInfo.EstateSettings.AllowDirectTeleport) - { - SceneObjectGroup telehub; - if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject)) != null) - { - List spawnPoints = RegionInfo.RegionSettings.SpawnPoints(); - bool banned = true; - foreach (SpawnPoint sp in spawnPoints) - { - Vector3 spawnPoint = sp.GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); - ILandObject land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); - if (land == null) - continue; - if (land.IsEitherBannedOrRestricted(agentID)) - continue; - banned = false; - break; - } - - if (banned) - { - if(Permissions.IsAdministrator(agentID) == false || Permissions.IsGridGod(agentID) == false) - { - reason = "No suitable landing point found"; - return false; - } - reason = "Administrative access only"; - return true; - } - } - } - - float posX = 128.0f; - float posY = 128.0f; - - if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY)) - { - // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID); - reason = "You are banned from the region on all parcels"; - return false; - } - } - else // Walking - { - ILandObject land = LandChannel.GetLandObject(position.X, position.Y); - if (land == null) - { - reason = "No parcel found"; - return false; - } - - bool banned = land.IsBannedFromLand(agentID); - bool restricted = land.IsRestrictedFromLand(agentID); - - if (banned || restricted) - { - if (banned) - reason = "You are banned from the parcel"; - else - reason = "The parcel is restricted"; - return false; - } - } + string oldVal; - reason = String.Empty; - return true; - } - - /// - /// This method deals with movement when an avatar is automatically moving (but this is distinct from the - /// autopilot that moves an avatar to a sit target!. - /// - /// - /// This is not intended as a permament location for this method. - /// - /// - private void HandleOnSignificantClientMovement(ScenePresence presence) - { - if (presence.MovingToTarget) - { - double distanceToTarget = Util.GetDistanceTo(presence.AbsolutePosition, presence.MoveToPositionTarget); -// m_log.DebugFormat( -// "[SCENE]: Abs pos of {0} is {1}, target {2}, distance {3}", -// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget, distanceToTarget); - - // Check the error term of the current position in relation to the target position - if (distanceToTarget <= ScenePresence.SIGNIFICANT_MOVEMENT) - { - // We are close enough to the target -// m_log.DebugFormat("[SCENEE]: Stopping autopilot of {0}", presence.Name); - - presence.Velocity = Vector3.Zero; - presence.AbsolutePosition = presence.MoveToPositionTarget; - presence.ResetMoveToTarget(); - - if (presence.Flying) - { - // A horrible hack to stop the avatar dead in its tracks rather than having them overshoot - // the target if flying. - // We really need to be more subtle (slow the avatar as it approaches the target) or at - // least be able to set collision status once, rather than 5 times to give it enough - // weighting so that that PhysicsActor thinks it really is colliding. - for (int i = 0; i < 5; i++) - presence.IsColliding = true; - - if (presence.LandAtTarget) - presence.Flying = false; - -// Vector3 targetPos = presence.MoveToPositionTarget; -// float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y]; -// if (targetPos.Z - terrainHeight < 0.2) -// { -// presence.Flying = false; -// } - } - -// m_log.DebugFormat( -// "[SCENE]: AgentControlFlags {0}, MovementFlag {1} for {2}", -// presence.AgentControlFlags, presence.MovementFlag, presence.Name); - } - else - { -// m_log.DebugFormat( -// "[SCENE]: Updating npc {0} at {1} for next movement to {2}", -// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget); - - Vector3 agent_control_v3 = new Vector3(); - presence.HandleMoveToTargetUpdate(1, ref agent_control_v3); - presence.AddNewMovement(agent_control_v3); - } - } - } - - // manage and select spawn points in sequence - public int SpawnPoint() - { - int spawnpoints = RegionInfo.RegionSettings.SpawnPoints().Count; - - if (spawnpoints == 0) - return 0; - - m_SpawnPoint++; - if (m_SpawnPoint > spawnpoints) - m_SpawnPoint = 1; - return m_SpawnPoint - 1; - } - - /// - /// Wrappers to get physics modules retrieve assets. - /// - /// - /// Has to be done this way - /// because we can't assign the asset service to physics directly - at the - /// time physics are instantiated it's not registered but it will be by - /// the time the first prim exists. - /// - /// - /// - public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback) - { - AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived); - } - - private void PhysicsAssetReceived(string id, Object sender, AssetBase asset) - { - AssetReceivedDelegate callback = (AssetReceivedDelegate)sender; - - callback(asset); - } - - public string GetExtraSetting(string name) - { - if (m_extraSettings == null) - return String.Empty; - - string val; - - if (!m_extraSettings.TryGetValue(name, out val)) - return String.Empty; - - return val; - } - - public void StoreExtraSetting(string name, string val) - { - if (m_extraSettings == null) - return; - - string oldVal; - - if (m_extraSettings.TryGetValue(name, out oldVal)) - { - if (oldVal == val) - return; - } - - m_extraSettings[name] = val; - - m_SimulationDataService.SaveExtra(RegionInfo.RegionID, name, val); - - m_eventManager.TriggerExtraSettingChanged(this, name, val); - } - - public void RemoveExtraSetting(string name) - { - if (m_extraSettings == null) - return; + if (m_extraSettings.TryGetValue(name, out oldVal)) + { + if (oldVal == val) + return; + } + + m_extraSettings[name] = val; + + m_SimulationDataService.SaveExtra(RegionInfo.RegionID, name, val); + + m_eventManager.TriggerExtraSettingChanged(this, name, val); + } + + public void RemoveExtraSetting(string name) + { + if (m_extraSettings == null) + return; + + if (!m_extraSettings.ContainsKey(name)) + return; - if (!m_extraSettings.ContainsKey(name)) - return; - - m_extraSettings.Remove(name); + m_extraSettings.Remove(name); - m_SimulationDataService.RemoveExtra(RegionInfo.RegionID, name); + m_SimulationDataService.RemoveExtra(RegionInfo.RegionID, name); - m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty); - } - } + m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty); + } + } } diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index b6da636..07d5f04 100755 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -63,7 +63,7 @@ namespace OpenSim.Region.Framework.Scenes // Determines the size of the array that is used to collect StatBlocks // for sending to the SimStats and SimExtraStatsCollector - private const int m_statisticArraySize = 26; + private const int m_statisticArraySize = 27; /// /// These are the IDs of stats sent in the StatsPacket to the viewer. @@ -109,10 +109,11 @@ namespace OpenSim.Region.Framework.Scenes SimSpareMs = 32, SimSleepMs = 33, SimIoPumpTime = 34, - UsersLoggingIn = 35, - TotalGeoPrim = 36, - TotalMesh = 37, - ThreadCount = 38 + FrameDilation = 35, + UsersLoggingIn = 36, + TotalGeoPrim = 37, + TotalMesh = 38, + ThreadCount = 39 } /// @@ -348,7 +349,7 @@ namespace OpenSim.Region.Framework.Scenes double simulationSumFrameTime; double physicsSumFrameTime; double networkSumFrameTime; - float timeDilation; + float frameDilation; int currentFrame; if (!m_scene.Active) @@ -466,16 +467,14 @@ namespace OpenSim.Region.Framework.Scenes else currentFrame = m_nextLocation - 1; - // Calculate the time dilation; which is currently based on the ratio between the sum of the - // physics and simulation rate, and the set minimum time to run the scene's update; minFrameTime - // is given in seconds so multiply by 1000 to convert it to milliseconds - timeDilation = (float)(m_simulationFrameTimeMilliseconds[currentFrame] + - m_physicsFrameTimeMilliseconds[currentFrame]) / (m_scene.MinFrameTime * 1000); + // Calculate the frame dilation; which is currently based on the ratio between the sum of the + // physics and simulation rate, and the set minimum time to run a scene's frame + frameDilation = (float)(m_simulationFrameTimeMilliseconds[currentFrame] + + m_physicsFrameTimeMilliseconds[currentFrame]) / m_scene.MinFrameTicks; // ORIGINAL code commented out until we have time to add our own sb[0].StatID = (uint) Stats.TimeDilation; - //sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); - sb[0].StatValue = timeDilation; + sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); sb[1].StatID = (uint) Stats.SimFPS; sb[1].StatValue = reportedFPS / m_statsUpdateFactor; @@ -547,23 +546,26 @@ namespace OpenSim.Region.Framework.Scenes sb[21].StatID = (uint)Stats.SimSpareMs; sb[21].StatValue = m_spareMS / framesUpdated; - // Added to track the number of users currently attempting to - // login to the region - sb[22].StatID = (uint)Stats.UsersLoggingIn; - sb[22].StatValue = m_usersLoggingIn; + // Current ratio between the sum of physics and sim rate, and the + // minimum time to run a scene's frame + sb[22].StatID = (uint)Stats.FrameDilation; + sb[22].StatValue = frameDilation; + + // Current number of users currently attemptint to login to region + sb[23].StatID = (uint)Stats.UsersLoggingIn; + sb[23].StatValue = m_usersLoggingIn; // Total number of geometric primitives in the scene - sb[23].StatID = (uint)Stats.TotalGeoPrim; - sb[23].StatValue = m_numGeoPrim; + sb[24].StatID = (uint)Stats.TotalGeoPrim; + sb[24].StatValue = m_numGeoPrim; // Total number of mesh objects in the scene - sb[24].StatID = (uint)Stats.TotalMesh; - sb[24].StatValue = m_numMesh; + sb[25].StatID = (uint)Stats.TotalMesh; + sb[25].StatValue = m_numMesh; - // Added to track the current number of threads that XEngine is - // using - sb[25].StatID = (uint)Stats.ThreadCount; - sb[25].StatValue = m_inUseThreads; + // Current number of threads that XEngine is using + sb[26].StatID = (uint)Stats.ThreadCount; + sb[26].StatValue = m_inUseThreads; for (int i = 0; i < m_statisticArraySize; i++) { -- cgit v1.1 From 9822692c12e40e2bebc390e5257be8e9f2c0c7b9 Mon Sep 17 00:00:00 2001 From: Robert Louden Date: Tue, 21 Apr 2015 16:30:02 -0400 Subject: Phase 2 additons with Frame Dilation metric. Test Plan: Compiles and runs successfully. Reviewers: szielinski Reviewed By: szielinski Differential Revision: http://cr.irl.ucf.edu/D268 --- bin/LukeSkywalker.IPNetwork.dll | Bin 18432 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 bin/LukeSkywalker.IPNetwork.dll diff --git a/bin/LukeSkywalker.IPNetwork.dll b/bin/LukeSkywalker.IPNetwork.dll deleted file mode 100644 index 25bcc2f..0000000 Binary files a/bin/LukeSkywalker.IPNetwork.dll and /dev/null differ -- cgit v1.1 From 0b3adc961b5fbb9771f494dfe644946d7deebe71 Mon Sep 17 00:00:00 2001 From: Steven Zielinski Date: Tue, 21 Apr 2015 15:33:54 -0400 Subject: Added in all metrics for Phase 1 except for Time Dilation. Test Plan: Tested on local opensim and firestorm. Not tested with JSON stats reporter. Reviewers: rlouden Reviewed By: rlouden Differential Revision: http://cr.irl.ucf.edu/D269 --- OpenSim/Region/Framework/Scenes/Scene.cs | 104 ++++++++++++++++- .../Region/Framework/Scenes/SimStatsReporter.cs | 123 +++++++++++++++++++-- 2 files changed, 218 insertions(+), 9 deletions(-) mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/Scene.cs mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/SimStatsReporter.cs diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs old mode 100644 new mode 100755 index 4715558..906c862 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1107,7 +1107,27 @@ namespace OpenSim.Region.Framework.Scenes #endregion Interest Management - StatsReporter = new SimStatsReporter(this); + // Acquire the statistics section of the OpenSim.ini file located + // in the bin directory + IConfig statisticsConfig = m_config.Configs["Statistics"]; + + // Confirm that the statistics section existed in the configuration + // file + if (statisticsConfig != null) + { + // Create the StatsReporter using the number of frames to store + // for the frame time statistics, or 10 frames if the config + // file doesn't contain a value + StatsReporter = new SimStatsReporter(this, + statisticsConfig.GetInt("NumberOfFrames", 10)); + } + else + { + // Create a StatsReporter with the current scene and a default + // 10 frames stored for the frame time statistics + StatsReporter = new SimStatsReporter(this); + } + StatsReporter.OnSendStatsResult += SendSimStatsPackets; StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; @@ -1607,6 +1627,21 @@ namespace OpenSim.Region.Framework.Scenes float physicsFPS = 0f; int previousFrameTick, tmpMS; + // These variables will be used to save the precise frame time using the + // Stopwatch class of Microsoft SDK; the times are recorded at the start + // and end of a particular section of code, and then used to calculate + // the frame times, which are the sums of the sections for each given name + double preciseTotalFrameTime = 0.0; + double preciseSimFrameTime = 0.0; + double precisePhysicsFrameTime = 0.0; + Stopwatch totalFrameStopwatch = new Stopwatch(); + Stopwatch simFrameStopwatch = new Stopwatch(); + Stopwatch physicsFrameStopwatch = new Stopwatch(); + + // Begin the stopwatch to keep track of the time that the frame + // started running to determine how long the frame took to complete + totalFrameStopwatch.Start(); + while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) { ++Frame; @@ -1622,25 +1657,62 @@ namespace OpenSim.Region.Framework.Scenes // Apply taints in terrain module to terrain in physics scene if (Frame % m_update_terrain == 0) { + // At several points inside the code there was a need to + // create a more precise measurement of time elapsed. + // This led to the addition of variables that have a + // similar function and thus remain tightly connected to + // their original counterparts. However, the original + // code is not receiving comments from our group because + // we don't feel right modifying the code to that degree + // at this point in time, the precise values all begin + // with the keyword precise tmpMS = Util.EnvironmentTickCount(); + + simFrameStopwatch.Start(); UpdateTerrain(); + + // Get the simulation frame time that the avatar force + // input took + simFrameStopwatch.Stop(); + preciseSimFrameTime = + simFrameStopwatch.Elapsed.TotalMilliseconds; terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); } tmpMS = Util.EnvironmentTickCount(); + + // Begin the stopwatch to track the time to prepare physics + physicsFrameStopwatch.Start(); if (PhysicsEnabled && Frame % m_update_physics == 0) m_sceneGraph.UpdatePreparePhysics(); + + // Get the time it took to prepare the physics, this + // would report the most precise time that physics was + // running on the machine and should the physics not be + // enabled will report the time it took to check if physics + // was enabled + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime = + physicsFrameStopwatch.Elapsed.TotalMilliseconds; physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); // Apply any pending avatar force input to the avatar's velocity tmpMS = Util.EnvironmentTickCount(); + simFrameStopwatch.Restart(); if (Frame % m_update_entitymovement == 0) m_sceneGraph.UpdateScenePresenceMovement(); + + // Get the simulation frame time that the avatar force input + // took + simFrameStopwatch.Stop(); + preciseSimFrameTime += + simFrameStopwatch.Elapsed.TotalMilliseconds; agentMS = Util.EnvironmentTickCountSubtract(tmpMS); // Perform the main physics update. This will do the actual work of moving objects and avatars according to their // velocity tmpMS = Util.EnvironmentTickCount(); + physicsFrameStopwatch.Restart(); if (Frame % m_update_physics == 0) { if (PhysicsEnabled) @@ -1649,8 +1721,16 @@ namespace OpenSim.Region.Framework.Scenes if (SynchronizeScene != null) SynchronizeScene(this); } + + // Add the main physics update time to the prepare physics + // time + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime += + physicsFrameStopwatch.Elapsed.TotalMilliseconds; physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); + // Start the stopwatch for the remainder of the simulation + simFrameStopwatch.Restart(); tmpMS = Util.EnvironmentTickCount(); // Check if any objects have reached their targets @@ -1738,6 +1818,11 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerRegionHeartbeatEnd(this); otherMS = eventMS + backupMS + terrainMS + landMS; + // Get the elapsed time for the simulation frame + simFrameStopwatch.Stop(); + preciseSimFrameTime += + simFrameStopwatch.Elapsed.TotalMilliseconds; + if (!UpdateOnTimer) { Watchdog.UpdateThread(); @@ -1754,6 +1839,14 @@ namespace OpenSim.Region.Framework.Scenes spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); } + // Get the total frame time + totalFrameStopwatch.Stop(); + preciseTotalFrameTime = + totalFrameStopwatch.Elapsed.TotalMilliseconds; + + // Restart the stopwatch for the total time of the next frame + totalFrameStopwatch.Restart(); + previousFrameTick = m_lastFrameTick; frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); m_lastFrameTick = Util.EnvironmentTickCount(); @@ -1771,6 +1864,15 @@ namespace OpenSim.Region.Framework.Scenes StatsReporter.AddSpareMS(spareMS); StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); + // Send the correct time values to the stats reporter for the + // frame times + StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime, + preciseSimFrameTime, precisePhysicsFrameTime, 0.0); + + // Send the correct number of frames that the physics library + // has processed to the stats reporter + StatsReporter.addPhysicsFrame(1); + // Optionally warn if a frame takes double the amount of time that it should. if (DebugUpdates && Util.EnvironmentTickCountSubtract( diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs old mode 100644 new mode 100755 index 8f1e345..6182bcd --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -213,6 +213,27 @@ namespace OpenSim.Region.Framework.Scenes private int m_objectCapacity = 45000; + // This is the number of frames that will be stored and then averaged for + // the Total, Simulation, Physics, and Network Frame Time; It is set to + // 10 by default but can be changed by the OpenSim.ini configuration file + // NumberOfFrames parameter + private int m_numberFramesStored = 10; + + // The arrays that will hold the time it took to run the past N frames, + // where N is the num_frames_to_average given by the configuration file + private double[] m_totalFrameTimeMilliseconds; + private double[] m_simulationFrameTimeMilliseconds; + private double[] m_physicsFrameTimeMilliseconds; + private double[] m_networkFrameTimeMilliseconds; + + // The location of the next time in milliseconds that will be + // (over)written when the next frame completes + private int m_nextLocation = 0; + + // The correct number of frames that have completed since the last stats + // update for physics + private int m_numberPhysicsFrames; + private Scene m_scene; private RegionInfo ReportingRegion; @@ -223,6 +244,13 @@ namespace OpenSim.Region.Framework.Scenes public SimStatsReporter(Scene scene) { + // Initialize the different frame time arrays to the correct sizes + m_totalFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_simulationFrameTimeMilliseconds = new + double[m_numberFramesStored]; + m_physicsFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_networkFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_scene = scene; m_reportedFpsCorrectionFactor = scene.MinFrameSeconds * m_nominalReportedFps; m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000); @@ -256,6 +284,13 @@ namespace OpenSim.Region.Framework.Scenes StatsManager.RegisterStat(SlowFramesStat); } + public SimStatsReporter(Scene scene, int numberOfFrames) : this (scene) + { + // Store the number of frames from the OpenSim.ini configuration + // file + m_numberFramesStored = numberOfFrames; + } + public void Close() { m_report.Elapsed -= TriggerStatsHeartbeat; @@ -289,6 +324,11 @@ namespace OpenSim.Region.Framework.Scenes private void statsHeartBeat(object sender, EventArgs e) { + double totalSumFrameTime; + double simulationSumFrameTime; + double physicsSumFrameTime; + double networkSumFrameTime; + if (!m_scene.Active) return; @@ -314,14 +354,21 @@ namespace OpenSim.Region.Framework.Scenes #region various statistic googly moogly + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window, this will be done as a + // new section given the title of our current project // We're going to lie about the FPS because we've been lying since 2008. The actual FPS is currently // locked at a maximum of 11. Maybe at some point this can change so that we're not lying. - int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); - + //int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); + int reportedFPS = m_fps; + // save the reported value so there is something available for llGetRegionFPS lastReportedSimFPS = reportedFPS / m_statsUpdateFactor; - float physfps = ((m_pfps / 1000)); + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window + //float physfps = ((m_pfps / 1000)); + float physfps = m_numberPhysicsFrames; //if (physfps > 600) //physfps = physfps - (physfps - 600); @@ -364,6 +411,26 @@ namespace OpenSim.Region.Framework.Scenes sb[i] = new SimStatsPacket.StatBlock(); } + // Resetting the sums of the frame times to prevent any errors + // in calculating the moving average for frame time + totalSumFrameTime = 0; + simulationSumFrameTime = 0; + physicsSumFrameTime = 0; + networkSumFrameTime = 0; + + // Loop through all the frames that were stored for the current + // heartbeat to process the moving average of frame times + for (int i = 0; i < m_numberFramesStored; i++) + { + // Sum up each frame time in order to calculate the moving + // average of frame time + totalSumFrameTime += m_totalFrameTimeMilliseconds[i]; + simulationSumFrameTime += + m_simulationFrameTimeMilliseconds[i]; + physicsSumFrameTime += m_physicsFrameTimeMilliseconds[i]; + networkSumFrameTime += m_networkFrameTimeMilliseconds[i]; + } + sb[0].StatID = (uint) Stats.TimeDilation; sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); @@ -388,21 +455,31 @@ namespace OpenSim.Region.Framework.Scenes sb[7].StatID = (uint) Stats.ActivePrim; sb[7].StatValue = m_activePrim; + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window sb[8].StatID = (uint)Stats.FrameMS; - sb[8].StatValue = m_frameMS / framesUpdated; + //sb[8].StatValue = m_frameMS / framesUpdated; + sb[8].StatValue = (float) totalSumFrameTime / + m_numberFramesStored; sb[9].StatID = (uint)Stats.NetMS; - sb[9].StatValue = m_netMS / framesUpdated; + //sb[9].StatValue = m_netMS / framesUpdated; + sb[9].StatValue = (float) networkSumFrameTime / + m_numberFramesStored; sb[10].StatID = (uint)Stats.PhysicsMS; - sb[10].StatValue = m_physicsMS / framesUpdated; + //sb[10].StatValue = m_physicsMS / framesUpdated; + sb[10].StatValue = (float) physicsSumFrameTime / + m_numberFramesStored; sb[11].StatID = (uint)Stats.ImageMS ; sb[11].StatValue = m_imageMS / framesUpdated; sb[12].StatID = (uint)Stats.OtherMS; - sb[12].StatValue = m_otherMS / framesUpdated; - + //sb[12].StatValue = m_otherMS / framesUpdated; + sb[12].StatValue = (float) simulationSumFrameTime / + m_numberFramesStored; + sb[13].StatID = (uint)Stats.InPacketsPerSecond; sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor); @@ -475,6 +552,10 @@ namespace OpenSim.Region.Framework.Scenes private void ResetValues() { + // Reset the number of frames that the physics library has + // processed since the last stats report + m_numberPhysicsFrames = 0; + m_timeDilation = 0; m_fps = 0; m_pfps = 0; @@ -605,6 +686,32 @@ namespace OpenSim.Region.Framework.Scenes m_otherMS += ms; } + public void addPhysicsFrame(int frames) + { + // Add the number of physics frames to the correct total physics + // frames + m_numberPhysicsFrames += frames; + } + + public void addFrameTimeMilliseconds(double total, double simulation, + double physics, double network) + { + // Save the frame times from the current frame into the appropriate + // arrays + m_totalFrameTimeMilliseconds[m_nextLocation] = total; + m_simulationFrameTimeMilliseconds[m_nextLocation] = simulation; + m_physicsFrameTimeMilliseconds[m_nextLocation] = physics; + m_networkFrameTimeMilliseconds[m_nextLocation] = network; + + // Update to the next location in the list + m_nextLocation++; + + // Since the list will begin to overwrite the oldest frame values + // first, the next location needs to loop back to the beginning of the + // list whenever it reaches the end + m_nextLocation = m_nextLocation % m_numberFramesStored; + } + public void AddPendingDownloads(int count) { m_pendingDownloads += count; -- cgit v1.1 From 2e7ace4e25c8e898177cd4ab4a859ceed314415d Mon Sep 17 00:00:00 2001 From: Robert Louden Date: Tue, 21 Apr 2015 18:42:30 -0400 Subject: Readded file to repository. Acciedently removed. --- bin/LukeSkywalker.IPNetwork.dll | Bin 0 -> 18432 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 bin/LukeSkywalker.IPNetwork.dll diff --git a/bin/LukeSkywalker.IPNetwork.dll b/bin/LukeSkywalker.IPNetwork.dll new file mode 100755 index 0000000..25bcc2f Binary files /dev/null and b/bin/LukeSkywalker.IPNetwork.dll differ -- cgit v1.1 From bebdc29effc9c588ea14c98190f029662a0f46a0 Mon Sep 17 00:00:00 2001 From: Steven Zielinski Date: Tue, 28 Apr 2015 15:52:25 -0400 Subject: Changed the 10 value to be a constant value inside of the Scene called m_DefaultNumberFramesStored. Test Plan: Tested on windows with the json stats reporter. Reviewers: rlouden, ssirigam, martin, kboswell, clattin Differential Revision: http://cr.irl.ucf.edu/D273 --- OpenSim/Region/Framework/Scenes/Scene.cs | 19 +++++++++++-------- OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 906c862..345cc81 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -61,6 +61,8 @@ namespace OpenSim.Region.Framework.Scenes { private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; + + public const int m_DefaultNumberFramesStored = 10; public delegate void SynchronizeSceneHandler(Scene scene); @@ -1115,17 +1117,18 @@ namespace OpenSim.Region.Framework.Scenes // file if (statisticsConfig != null) { - // Create the StatsReporter using the number of frames to store - // for the frame time statistics, or 10 frames if the config - // file doesn't contain a value - StatsReporter = new SimStatsReporter(this, - statisticsConfig.GetInt("NumberOfFrames", 10)); + // Create the StatsReporter using the number of frames to store + // for the frame time statistics, or 10 frames if the config + // file doesn't contain a value + StatsReporter = new SimStatsReporter(this, + statisticsConfig.GetInt("NumberOfFrames", + m_DefaultNumberFramesStored)); } else { - // Create a StatsReporter with the current scene and a default - // 10 frames stored for the frame time statistics - StatsReporter = new SimStatsReporter(this); + // Create a StatsReporter with the current scene and a default + // 10 frames stored for the frame time statistics + StatsReporter = new SimStatsReporter(this); } StatsReporter.OnSendStatsResult += SendSimStatsPackets; diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 6182bcd..d90d2b3 100755 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -217,7 +217,7 @@ namespace OpenSim.Region.Framework.Scenes // the Total, Simulation, Physics, and Network Frame Time; It is set to // 10 by default but can be changed by the OpenSim.ini configuration file // NumberOfFrames parameter - private int m_numberFramesStored = 10; + private int m_numberFramesStored = Scene.m_DefaultNumberFramesStored; // The arrays that will hold the time it took to run the past N frames, // where N is the num_frames_to_average given by the configuration file -- cgit v1.1 From cb3c6038af6cf7e3d749250c4aa2596967ef8d70 Mon Sep 17 00:00:00 2001 From: Steven Zielinski Date: Wed, 29 Apr 2015 08:51:19 -0400 Subject: Changed the 10 value to be a constant value inside of the Scene called m_DefaultNumberFramesStored. Test Plan: Tested on windows with the json stats reporter. Reviewers: rlouden, kboswell, clattin, ssirigam, martin Reviewed By: rlouden, kboswell, clattin, ssirigam, martin Differential Revision: http://cr.irl.ucf.edu/D273 --- OpenSim/Region/Framework/Scenes/Scene.cs | 4 ++-- OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 345cc81..438dce9 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -62,7 +62,7 @@ namespace OpenSim.Region.Framework.Scenes private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; - public const int m_DefaultNumberFramesStored = 10; + public const int m_defaultNumberFramesStored = 10; public delegate void SynchronizeSceneHandler(Scene scene); @@ -1122,7 +1122,7 @@ namespace OpenSim.Region.Framework.Scenes // file doesn't contain a value StatsReporter = new SimStatsReporter(this, statisticsConfig.GetInt("NumberOfFrames", - m_DefaultNumberFramesStored)); + m_defaultNumberFramesStored)); } else { diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index d90d2b3..0eab898 100755 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -217,7 +217,7 @@ namespace OpenSim.Region.Framework.Scenes // the Total, Simulation, Physics, and Network Frame Time; It is set to // 10 by default but can be changed by the OpenSim.ini configuration file // NumberOfFrames parameter - private int m_numberFramesStored = Scene.m_DefaultNumberFramesStored; + private int m_numberFramesStored = Scene.m_defaultNumberFramesStored; // The arrays that will hold the time it took to run the past N frames, // where N is the num_frames_to_average given by the configuration file -- cgit v1.1 From 625452b84baf68775454209fd2d3198f138762f2 Mon Sep 17 00:00:00 2001 From: Steven Zielinski Date: Thu, 30 Apr 2015 15:45:11 -0400 Subject: Updated phase 2 to have the changes originally done in phase 1 for the defaultNumberFramesStored. Test Plan: Tested using opensim standalone on windows with json stats. Reviewers: rlouden Reviewed By: rlouden Differential Revision: http://cr.irl.ucf.edu/D275 --- OpenSim/Region/Framework/Scenes/Scene.cs | 11109 ++++++++++--------- .../Region/Framework/Scenes/SimStatsReporter.cs | 2 +- 2 files changed, 5557 insertions(+), 5554 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 31e4ee0..c0111d9 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1,29 +1,29 @@ /* - * 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 OpenSimulator 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. - */ +* 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 OpenSimulator 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.Generic; @@ -55,5975 +55,5978 @@ using PermissionMask = OpenSim.Framework.PermissionMask; namespace OpenSim.Region.Framework.Scenes { - public delegate bool FilterAvatarList(ScenePresence avatar); - - public partial class Scene : SceneBase - { - private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; - private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; - - public delegate void SynchronizeSceneHandler(Scene scene); - - #region Fields - - public bool EmergencyMonitoring = false; - - /// - /// Show debug information about animations. - /// - public bool DebugAnimations { get; set; } - - /// - /// Show debug information about teleports. - /// - public bool DebugTeleporting { get; set; } - - /// - /// Show debug information about the scene loop. - /// - public bool DebugUpdates { get; set; } - - /// - /// If true then the scene is saved to persistent storage periodically, every m_update_backup frames and - /// if objects meet required conditions (m_dontPersistBefore and m_dontPersistAfter). - /// - /// - /// Even if false, the scene will still be saved on clean shutdown. - /// FIXME: Currently, setting this to false will mean that objects are not periodically returned from parcels. - /// This needs to be fixed. - /// - public bool PeriodicBackup { get; set; } - - /// - /// If false then the scene is never saved to persistence storage even if PeriodicBackup == true and even - /// if the scene is being shut down for the final time. - /// - public bool UseBackup { get; set; } - - /// - /// If false then physical objects are disabled, though collisions will continue as normal. - /// - public bool PhysicsEnabled - { - get - { - return m_physicsEnabled; - } - - set - { - m_physicsEnabled = value; + public delegate bool FilterAvatarList(ScenePresence avatar); + + public partial class Scene : SceneBase + { + private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; + private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; + + public const int m_defaultNumberFramesStored = 10; + + public delegate void SynchronizeSceneHandler(Scene scene); + + #region Fields + + public bool EmergencyMonitoring = false; + + /// + /// Show debug information about animations. + /// + public bool DebugAnimations { get; set; } + + /// + /// Show debug information about teleports. + /// + public bool DebugTeleporting { get; set; } + + /// + /// Show debug information about the scene loop. + /// + public bool DebugUpdates { get; set; } + + /// + /// If true then the scene is saved to persistent storage periodically, every m_update_backup frames and + /// if objects meet required conditions (m_dontPersistBefore and m_dontPersistAfter). + /// + /// + /// Even if false, the scene will still be saved on clean shutdown. + /// FIXME: Currently, setting this to false will mean that objects are not periodically returned from parcels. + /// This needs to be fixed. + /// + public bool PeriodicBackup { get; set; } + + /// + /// If false then the scene is never saved to persistence storage even if PeriodicBackup == true and even + /// if the scene is being shut down for the final time. + /// + public bool UseBackup { get; set; } + + /// + /// If false then physical objects are disabled, though collisions will continue as normal. + /// + public bool PhysicsEnabled + { + get + { + return m_physicsEnabled; + } + + set + { + m_physicsEnabled = value; + + if (PhysicsScene != null) + { + IPhysicsParameters physScene = PhysicsScene as IPhysicsParameters; + + if (physScene != null) + physScene.SetPhysicsParameter( + "Active", m_physicsEnabled.ToString(), PhysParameterEntry.APPLY_TO_NONE); + } + } + } + + private bool m_physicsEnabled; + + /// + /// If false then scripts are not enabled on the smiulator + /// + public bool ScriptsEnabled + { + get { return m_scripts_enabled; } + set + { + if (m_scripts_enabled != value) + { + if (!value) + { + m_log.Info("Stopping all Scripts in Scene"); + + EntityBase[] entities = Entities.GetEntities(); + foreach (EntityBase ent in entities) + { + if (ent is SceneObjectGroup) + ((SceneObjectGroup)ent).RemoveScriptInstances(false); + } + } + else + { + m_log.Info("Starting all Scripts in Scene"); + + EntityBase[] entities = Entities.GetEntities(); + foreach (EntityBase ent in entities) + { + if (ent is SceneObjectGroup) + { + SceneObjectGroup sog = (SceneObjectGroup)ent; + sog.CreateScriptInstances(0, false, DefaultScriptEngine, 0); + sog.ResumeScripts(); + } + } + } + + m_scripts_enabled = value; + } + } + } + private bool m_scripts_enabled; + + public SynchronizeSceneHandler SynchronizeScene; + + /// + /// Used to prevent simultaneous calls to code that adds and removes agents. + /// + private object m_removeClientLock = new object(); + + /// + /// Statistical information for this scene. + /// + public SimStatsReporter StatsReporter { get; private set; } + + /// + /// Controls whether physics can be applied to prims. Even if false, prims still have entries in a + /// PhysicsScene in order to perform collision detection + /// + public bool PhysicalPrims { get; private set; } + + /// + /// Controls whether prims can be collided with. + /// + /// + /// If this is set to false then prims cannot be subject to physics either. + /// + public bool CollidablePrims { get; private set; } + + /// + /// Minimum value of the size of a non-physical prim in each axis + /// + public float m_minNonphys = 0.001f; + + /// + /// Maximum value of the size of a non-physical prim in each axis + /// + public float m_maxNonphys = 256; + + /// + /// Minimum value of the size of a physical prim in each axis + /// + public float m_minPhys = 0.01f; + + /// + /// Maximum value of the size of a physical prim in each axis + /// + public float m_maxPhys = 64; + + /// + /// Max prims an object will hold + /// + public int m_linksetCapacity = 0; + + public bool m_clampPrimSize; + public bool m_trustBinaries; + public bool m_allowScriptCrossings = true; + + /// + /// Can avatars cross from and to this region? + /// + public bool AllowAvatarCrossing { get; set; } + + public bool m_useFlySlow; + public bool m_useTrashOnDelete = true; + + /// + /// Temporarily setting to trigger appearance resends at 60 second intervals. + /// + public bool SendPeriodicAppearanceUpdates { get; set; } + + /// + /// How much a root agent has to change position before updates are sent to viewers. + /// + public float RootPositionUpdateTolerance { get; set; } + + /// + /// How much a root agent has to rotate before updates are sent to viewers. + /// + public float RootRotationUpdateTolerance { get; set; } + + /// + /// How much a root agent has to change velocity before updates are sent to viewers. + /// + public float RootVelocityUpdateTolerance { get; set; } + + /// + /// If greater than 1, we only send terse updates to other root agents on every n updates. + /// + public int RootTerseUpdatePeriod { get; set; } + + /// + /// If greater than 1, we only send terse updates to child agents on every n updates. + /// + public int ChildTerseUpdatePeriod { get; set; } + + protected float m_defaultDrawDistance = 255.0f; + public float DefaultDrawDistance + { + // get { return m_defaultDrawDistance; } + get + { + if (RegionInfo != null) + { + float largestDimension = Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); + m_defaultDrawDistance = Math.Max(m_defaultDrawDistance, largestDimension); + + } + return m_defaultDrawDistance; + } + } + + private List m_AllowedViewers = new List(); + private List m_BannedViewers = new List(); + + // TODO: need to figure out how allow client agents but deny + // root agents when ACL denies access to root agent + public bool m_strictAccessControl = true; + + public int MaxUndoCount { get; set; } + + public bool SeeIntoRegion { get; set; } + + // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; + public bool LoginLock = false; + + public bool StartDisabled = false; + public bool LoadingPrims; + public IXfer XferManager; + + // the minimum time that must elapse before a changed object will be considered for persisted + public long m_dontPersistBefore = DEFAULT_MIN_TIME_FOR_PERSISTENCE * 10000000L; + // the maximum time that must elapse before a changed object will be considered for persisted + public long m_persistAfter = DEFAULT_MAX_TIME_FOR_PERSISTENCE * 10000000L; + + protected int m_splitRegionID; + protected Timer m_restartWaitTimer = new Timer(); + protected List m_regionRestartNotifyList = new List(); + protected List m_neighbours = new List(); + protected string m_simulatorVersion = "OpenSimulator Server"; + protected AgentCircuitManager m_authenticateHandler; + protected SceneCommunicationService m_sceneGridService; + + protected ISimulationDataService m_SimulationDataService; + protected IEstateDataService m_EstateDataService; + protected IAssetService m_AssetService; + protected IAuthorizationService m_AuthorizationService; + protected IInventoryService m_InventoryService; + protected IGridService m_GridService; + protected ILibraryService m_LibraryService; + protected ISimulationService m_simulationService; + protected IAuthenticationService m_AuthenticationService; + protected IPresenceService m_PresenceService; + protected IUserAccountService m_UserAccountService; + protected IAvatarService m_AvatarService; + protected IGridUserService m_GridUserService; + + protected IXMLRPC m_xmlrpcModule; + protected IWorldComm m_worldCommModule; + protected IAvatarFactoryModule m_AvatarFactory; + protected IConfigSource m_config; + protected IRegionSerialiserModule m_serialiser; + protected IDialogModule m_dialogModule; + protected ICapabilitiesModule m_capsModule; + protected IGroupsModule m_groupsModule; + + private Dictionary m_extraSettings; + + /// + /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer + /// rather than on a single thread that sleeps. + /// + public bool UpdateOnTimer { get; set; } + + /// + /// Only used if we are updating scene on a timer rather than sleeping a thread. + /// + private Timer m_sceneUpdateTimer; + + /// + /// Current scene frame number + /// + public uint Frame + { + get; + protected set; + } + + /// + /// Current maintenance run number + /// + public uint MaintenanceRun { get; private set; } + + /// + /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we + /// will sleep for the remaining period. + /// + /// + /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations + /// occur too quickly (viewer 1) or with even more slide (viewer 2). + /// + public int MinFrameTicks + { + get { return m_minFrameTicks; } + private set + { + m_minFrameTicks = value; + MinFrameSeconds = (float)m_minFrameTicks / 1000; + } + } + private int m_minFrameTicks; + + /// + /// The minimum length of time in seconds that will be taken for a scene frame. + /// + /// + /// Always derived from MinFrameTicks. + /// + public float MinFrameSeconds { get; private set; } + + /// + /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we + /// will sleep for the remaining period. + /// + /// + /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations + /// occur too quickly (viewer 1) or with even more slide (viewer 2). + /// + public int MinMaintenanceTicks { get; set; } + + private int m_update_physics = 1; + private int m_update_entitymovement = 1; + private int m_update_objects = 1; + private int m_update_presences = 1; // Update scene presence movements + private int m_update_events = 1; + private int m_update_backup = 200; + private int m_update_terrain = 50; + // private int m_update_land = 1; + private int m_update_coarse_locations = 50; + private int m_update_temp_cleaning = 180; + + private int agentMS; + private int frameMS; + private int physicsMS2; + private int physicsMS; + private int otherMS; + private int tempOnRezMS; + private int eventMS; + private int backupMS; + private int terrainMS; + private int landMS; + private int spareMS; + + /// + /// Tick at which the last frame was processed. + /// + private int m_lastFrameTick; + + /// + /// Tick at which the last maintenance run occurred. + /// + private int m_lastMaintenanceTick; + + /// + /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched + /// asynchronously from the update loop. + /// + private bool m_cleaningTemps = false; + + /// + /// Used to control main scene thread looping time when not updating via timer. + /// + private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false); + + /// + /// Used to control maintenance thread runs. + /// + private ManualResetEvent m_maintenanceWaitEvent = new ManualResetEvent(false); + + // TODO: Possibly stop other classes being able to manipulate this directly. + private SceneGraph m_sceneGraph; + private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing + private volatile bool m_backingup; + private Dictionary m_returns = new Dictionary(); + private Dictionary m_groupsWithTargets = new Dictionary(); + + private string m_defaultScriptEngine; + + /// + /// Tick at which the last login occurred. + /// + private int m_LastLogin; + + /// + /// Thread that runs the scene loop. + /// + private Thread m_heartbeatThread; + + /// + /// True if these scene is in the process of shutting down or is shutdown. + /// + public bool ShuttingDown + { + get { return m_shuttingDown; } + } + private volatile bool m_shuttingDown; + + /// + /// Is the scene active? + /// + /// + /// If false, maintenance and update loops are not being run, though after setting to false update may still + /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if + /// the scene is not active. + /// + public bool Active + { + get { return m_active; } + set + { + if (value) + { + if (!m_active) + Start(false); + } + else + { + // This appears assymetric with Start() above but is not - setting m_active = false stops the loops + // XXX: Possibly this should be in an explicit Stop() method for symmetry. + m_active = false; + } + } + } + private volatile bool m_active; + + /// + /// If true then updates are running. This may be true for a short period after a scene is de-activated. + /// + public bool IsRunning { get { return m_isRunning; } } + private volatile bool m_isRunning; + + private Timer m_mapGenerationTimer = new Timer(); + private bool m_generateMaptiles; + + #endregion Fields + + #region Properties + + /* Used by the loadbalancer plugin on GForge */ + public int SplitRegionID + { + get { return m_splitRegionID; } + set { m_splitRegionID = value; } + } + + public new float TimeDilation + { + get { return m_sceneGraph.PhysicsScene.TimeDilation; } + } + + public void setThreadCount(int inUseThreads) + { + // Just pass the thread count information on its way as the Scene + // does not require the value for anything at this time + StatsReporter.SetThreadCount(inUseThreads); + } + + public SceneCommunicationService SceneGridService + { + get { return m_sceneGridService; } + } + + public ISimulationDataService SimulationDataService + { + get + { + if (m_SimulationDataService == null) + { + m_SimulationDataService = RequestModuleInterface(); + + if (m_SimulationDataService == null) + { + throw new Exception("No ISimulationDataService available."); + } + } + + return m_SimulationDataService; + } + } + + public IEstateDataService EstateDataService + { + get + { + if (m_EstateDataService == null) + { + m_EstateDataService = RequestModuleInterface(); + + if (m_EstateDataService == null) + { + throw new Exception("No IEstateDataService available."); + } + } - if (PhysicsScene != null) - { - IPhysicsParameters physScene = PhysicsScene as IPhysicsParameters; - - if (physScene != null) - physScene.SetPhysicsParameter( - "Active", m_physicsEnabled.ToString(), PhysParameterEntry.APPLY_TO_NONE); - } - } - } - - private bool m_physicsEnabled; - - /// - /// If false then scripts are not enabled on the smiulator - /// - public bool ScriptsEnabled - { - get { return m_scripts_enabled; } - set - { - if (m_scripts_enabled != value) - { - if (!value) - { - m_log.Info("Stopping all Scripts in Scene"); - - EntityBase[] entities = Entities.GetEntities(); - foreach (EntityBase ent in entities) - { - if (ent is SceneObjectGroup) - ((SceneObjectGroup)ent).RemoveScriptInstances(false); - } - } - else - { - m_log.Info("Starting all Scripts in Scene"); - - EntityBase[] entities = Entities.GetEntities(); - foreach (EntityBase ent in entities) - { - if (ent is SceneObjectGroup) - { - SceneObjectGroup sog = (SceneObjectGroup)ent; - sog.CreateScriptInstances(0, false, DefaultScriptEngine, 0); - sog.ResumeScripts(); - } - } - } - - m_scripts_enabled = value; - } - } - } - private bool m_scripts_enabled; - - public SynchronizeSceneHandler SynchronizeScene; - - /// - /// Used to prevent simultaneous calls to code that adds and removes agents. - /// - private object m_removeClientLock = new object(); - - /// - /// Statistical information for this scene. - /// - public SimStatsReporter StatsReporter { get; private set; } - - /// - /// Controls whether physics can be applied to prims. Even if false, prims still have entries in a - /// PhysicsScene in order to perform collision detection - /// - public bool PhysicalPrims { get; private set; } - - /// - /// Controls whether prims can be collided with. - /// - /// - /// If this is set to false then prims cannot be subject to physics either. - /// - public bool CollidablePrims { get; private set; } - - /// - /// Minimum value of the size of a non-physical prim in each axis - /// - public float m_minNonphys = 0.001f; - - /// - /// Maximum value of the size of a non-physical prim in each axis - /// - public float m_maxNonphys = 256; - - /// - /// Minimum value of the size of a physical prim in each axis - /// - public float m_minPhys = 0.01f; - - /// - /// Maximum value of the size of a physical prim in each axis - /// - public float m_maxPhys = 64; - - /// - /// Max prims an object will hold - /// - public int m_linksetCapacity = 0; - - public bool m_clampPrimSize; - public bool m_trustBinaries; - public bool m_allowScriptCrossings = true; - - /// - /// Can avatars cross from and to this region? - /// - public bool AllowAvatarCrossing { get; set; } - - public bool m_useFlySlow; - public bool m_useTrashOnDelete = true; - - /// - /// Temporarily setting to trigger appearance resends at 60 second intervals. - /// - public bool SendPeriodicAppearanceUpdates { get; set; } - - /// - /// How much a root agent has to change position before updates are sent to viewers. - /// - public float RootPositionUpdateTolerance { get; set; } - - /// - /// How much a root agent has to rotate before updates are sent to viewers. - /// - public float RootRotationUpdateTolerance { get; set; } - - /// - /// How much a root agent has to change velocity before updates are sent to viewers. - /// - public float RootVelocityUpdateTolerance { get; set; } - - /// - /// If greater than 1, we only send terse updates to other root agents on every n updates. - /// - public int RootTerseUpdatePeriod { get; set; } - - /// - /// If greater than 1, we only send terse updates to child agents on every n updates. - /// - public int ChildTerseUpdatePeriod { get; set; } - - protected float m_defaultDrawDistance = 255.0f; - public float DefaultDrawDistance - { - // get { return m_defaultDrawDistance; } - get - { - if (RegionInfo != null) - { - float largestDimension = Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); - m_defaultDrawDistance = Math.Max(m_defaultDrawDistance, largestDimension); - - } - return m_defaultDrawDistance; - } - } - - private List m_AllowedViewers = new List(); - private List m_BannedViewers = new List(); - - // TODO: need to figure out how allow client agents but deny - // root agents when ACL denies access to root agent - public bool m_strictAccessControl = true; - - public int MaxUndoCount { get; set; } - - public bool SeeIntoRegion { get; set; } - - // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; - public bool LoginLock = false; - - public bool StartDisabled = false; - public bool LoadingPrims; - public IXfer XferManager; - - // the minimum time that must elapse before a changed object will be considered for persisted - public long m_dontPersistBefore = DEFAULT_MIN_TIME_FOR_PERSISTENCE * 10000000L; - // the maximum time that must elapse before a changed object will be considered for persisted - public long m_persistAfter = DEFAULT_MAX_TIME_FOR_PERSISTENCE * 10000000L; - - protected int m_splitRegionID; - protected Timer m_restartWaitTimer = new Timer(); - protected List m_regionRestartNotifyList = new List(); - protected List m_neighbours = new List(); - protected string m_simulatorVersion = "OpenSimulator Server"; - protected AgentCircuitManager m_authenticateHandler; - protected SceneCommunicationService m_sceneGridService; - - protected ISimulationDataService m_SimulationDataService; - protected IEstateDataService m_EstateDataService; - protected IAssetService m_AssetService; - protected IAuthorizationService m_AuthorizationService; - protected IInventoryService m_InventoryService; - protected IGridService m_GridService; - protected ILibraryService m_LibraryService; - protected ISimulationService m_simulationService; - protected IAuthenticationService m_AuthenticationService; - protected IPresenceService m_PresenceService; - protected IUserAccountService m_UserAccountService; - protected IAvatarService m_AvatarService; - protected IGridUserService m_GridUserService; - - protected IXMLRPC m_xmlrpcModule; - protected IWorldComm m_worldCommModule; - protected IAvatarFactoryModule m_AvatarFactory; - protected IConfigSource m_config; - protected IRegionSerialiserModule m_serialiser; - protected IDialogModule m_dialogModule; - protected ICapabilitiesModule m_capsModule; - protected IGroupsModule m_groupsModule; - - private Dictionary m_extraSettings; - - /// - /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer - /// rather than on a single thread that sleeps. - /// - public bool UpdateOnTimer { get; set; } - - /// - /// Only used if we are updating scene on a timer rather than sleeping a thread. - /// - private Timer m_sceneUpdateTimer; - - /// - /// Current scene frame number - /// - public uint Frame - { - get; - protected set; - } - - /// - /// Current maintenance run number - /// - public uint MaintenanceRun { get; private set; } - - /// - /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we - /// will sleep for the remaining period. - /// - /// - /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations - /// occur too quickly (viewer 1) or with even more slide (viewer 2). - /// - public int MinFrameTicks - { - get { return m_minFrameTicks; } - private set - { - m_minFrameTicks = value; - MinFrameSeconds = (float)m_minFrameTicks / 1000; - } - } - private int m_minFrameTicks; - - /// - /// The minimum length of time in seconds that will be taken for a scene frame. - /// - /// - /// Always derived from MinFrameTicks. - /// - public float MinFrameSeconds { get; private set; } - - /// - /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we - /// will sleep for the remaining period. - /// - /// - /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations - /// occur too quickly (viewer 1) or with even more slide (viewer 2). - /// - public int MinMaintenanceTicks { get; set; } - - private int m_update_physics = 1; - private int m_update_entitymovement = 1; - private int m_update_objects = 1; - private int m_update_presences = 1; // Update scene presence movements - private int m_update_events = 1; - private int m_update_backup = 200; - private int m_update_terrain = 50; - // private int m_update_land = 1; - private int m_update_coarse_locations = 50; - private int m_update_temp_cleaning = 180; - - private int agentMS; - private int frameMS; - private int physicsMS2; - private int physicsMS; - private int otherMS; - private int tempOnRezMS; - private int eventMS; - private int backupMS; - private int terrainMS; - private int landMS; - private int spareMS; - - /// - /// Tick at which the last frame was processed. - /// - private int m_lastFrameTick; - - /// - /// Tick at which the last maintenance run occurred. - /// - private int m_lastMaintenanceTick; - - /// - /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched - /// asynchronously from the update loop. - /// - private bool m_cleaningTemps = false; - - /// - /// Used to control main scene thread looping time when not updating via timer. - /// - private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false); - - /// - /// Used to control maintenance thread runs. - /// - private ManualResetEvent m_maintenanceWaitEvent = new ManualResetEvent(false); - - // TODO: Possibly stop other classes being able to manipulate this directly. - private SceneGraph m_sceneGraph; - private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing - private volatile bool m_backingup; - private Dictionary m_returns = new Dictionary(); - private Dictionary m_groupsWithTargets = new Dictionary(); - - private string m_defaultScriptEngine; - - /// - /// Tick at which the last login occurred. - /// - private int m_LastLogin; - - /// - /// Thread that runs the scene loop. - /// - private Thread m_heartbeatThread; - - /// - /// True if these scene is in the process of shutting down or is shutdown. - /// - public bool ShuttingDown - { - get { return m_shuttingDown; } - } - private volatile bool m_shuttingDown; - - /// - /// Is the scene active? - /// - /// - /// If false, maintenance and update loops are not being run, though after setting to false update may still - /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if - /// the scene is not active. - /// - public bool Active - { - get { return m_active; } - set - { - if (value) - { - if (!m_active) - Start(false); + return m_EstateDataService; } - else + } + + public IAssetService AssetService + { + get { - // This appears assymetric with Start() above but is not - setting m_active = false stops the loops - // XXX: Possibly this should be in an explicit Stop() method for symmetry. - m_active = false; - } - } - } - private volatile bool m_active; + if (m_AssetService == null) + { + m_AssetService = RequestModuleInterface(); - /// - /// If true then updates are running. This may be true for a short period after a scene is de-activated. - /// - public bool IsRunning { get { return m_isRunning; } } - private volatile bool m_isRunning; + if (m_AssetService == null) + { + throw new Exception("No IAssetService available."); + } + } - private Timer m_mapGenerationTimer = new Timer(); - private bool m_generateMaptiles; + return m_AssetService; + } + } - #endregion Fields + public IAuthorizationService AuthorizationService + { + get + { + if (m_AuthorizationService == null) + { + m_AuthorizationService = RequestModuleInterface(); - #region Properties + //if (m_AuthorizationService == null) + //{ + // // don't throw an exception if no authorization service is set for the time being + // m_log.InfoFormat("[SCENE]: No Authorization service is configured"); + //} + } - /* Used by the loadbalancer plugin on GForge */ - public int SplitRegionID - { - get { return m_splitRegionID; } - set { m_splitRegionID = value; } - } + return m_AuthorizationService; + } + } - public new float TimeDilation - { - get { return m_sceneGraph.PhysicsScene.TimeDilation; } - } + public IInventoryService InventoryService + { + get + { + if (m_InventoryService == null) + { + m_InventoryService = RequestModuleInterface(); - public void setThreadCount(int inUseThreads) - { - // Just pass the thread count information on its way as the Scene - // does not require the value for anything at this time - StatsReporter.SetThreadCount(inUseThreads); - } + if (m_InventoryService == null) + { + throw new Exception("No IInventoryService available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. Please also check that you have the correct version of your inventory service dll. Sometimes old versions of this dll will still exist. Do a clean checkout and re-create the opensim.ini from the opensim.ini.example."); + } + } - public SceneCommunicationService SceneGridService - { - get { return m_sceneGridService; } - } + return m_InventoryService; + } + } - public ISimulationDataService SimulationDataService - { - get - { - if (m_SimulationDataService == null) + public IGridService GridService + { + get { - m_SimulationDataService = RequestModuleInterface(); + if (m_GridService == null) + { + m_GridService = RequestModuleInterface(); - if (m_SimulationDataService == null) - { - throw new Exception("No ISimulationDataService available."); - } - } + if (m_GridService == null) + { + throw new Exception("No IGridService available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. Please also check that you have the correct version of your inventory service dll. Sometimes old versions of this dll will still exist. Do a clean checkout and re-create the opensim.ini from the opensim.ini.example."); + } + } - return m_SimulationDataService; - } - } + return m_GridService; + } + } - public IEstateDataService EstateDataService - { - get - { - if (m_EstateDataService == null) + public ILibraryService LibraryService + { + get { - m_EstateDataService = RequestModuleInterface(); + if (m_LibraryService == null) + m_LibraryService = RequestModuleInterface(); - if (m_EstateDataService == null) - { - throw new Exception("No IEstateDataService available."); - } + return m_LibraryService; } + } - return m_EstateDataService; - } - } - - public IAssetService AssetService - { - get - { - if (m_AssetService == null) - { - m_AssetService = RequestModuleInterface(); - - if (m_AssetService == null) - { - throw new Exception("No IAssetService available."); - } - } - - return m_AssetService; - } - } - - public IAuthorizationService AuthorizationService - { - get - { - if (m_AuthorizationService == null) - { - m_AuthorizationService = RequestModuleInterface(); - - //if (m_AuthorizationService == null) - //{ - // // don't throw an exception if no authorization service is set for the time being - // m_log.InfoFormat("[SCENE]: No Authorization service is configured"); - //} - } - - return m_AuthorizationService; - } - } - - public IInventoryService InventoryService - { - get - { - if (m_InventoryService == null) - { - m_InventoryService = RequestModuleInterface(); - - if (m_InventoryService == null) - { - throw new Exception("No IInventoryService available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. Please also check that you have the correct version of your inventory service dll. Sometimes old versions of this dll will still exist. Do a clean checkout and re-create the opensim.ini from the opensim.ini.example."); - } - } - - return m_InventoryService; - } - } - - public IGridService GridService - { - get - { - if (m_GridService == null) - { - m_GridService = RequestModuleInterface(); - - if (m_GridService == null) - { - throw new Exception("No IGridService available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. Please also check that you have the correct version of your inventory service dll. Sometimes old versions of this dll will still exist. Do a clean checkout and re-create the opensim.ini from the opensim.ini.example."); - } - } - - return m_GridService; - } - } - - public ILibraryService LibraryService - { - get - { - if (m_LibraryService == null) - m_LibraryService = RequestModuleInterface(); - - return m_LibraryService; - } - } - - public ISimulationService SimulationService - { - get - { - if (m_simulationService == null) - m_simulationService = RequestModuleInterface(); - - return m_simulationService; - } - } - - public IAuthenticationService AuthenticationService - { - get - { - if (m_AuthenticationService == null) - m_AuthenticationService = RequestModuleInterface(); - return m_AuthenticationService; - } - } - - public IPresenceService PresenceService - { - get - { - if (m_PresenceService == null) - m_PresenceService = RequestModuleInterface(); - return m_PresenceService; - } - } - - public IUserAccountService UserAccountService - { - get - { - if (m_UserAccountService == null) - m_UserAccountService = RequestModuleInterface(); - return m_UserAccountService; - } - } - - public IAvatarService AvatarService - { - get - { - if (m_AvatarService == null) - m_AvatarService = RequestModuleInterface(); - return m_AvatarService; - } - } - - public IGridUserService GridUserService - { - get - { - if (m_GridUserService == null) - m_GridUserService = RequestModuleInterface(); - return m_GridUserService; - } - } - - public IAttachmentsModule AttachmentsModule { get; set; } - public IEntityTransferModule EntityTransferModule { get; private set; } - public IAgentAssetTransactions AgentTransactionsModule { get; private set; } - public IUserManagement UserManagementModule { get; private set; } - - public IAvatarFactoryModule AvatarFactory - { - get { return m_AvatarFactory; } - } - - public ICapabilitiesModule CapsModule - { - get { return m_capsModule; } - } - - public int MonitorFrameTime { get { return frameMS; } } - public int MonitorPhysicsUpdateTime { get { return physicsMS; } } - public int MonitorPhysicsSyncTime { get { return physicsMS2; } } - public int MonitorOtherTime { get { return otherMS; } } - public int MonitorTempOnRezTime { get { return tempOnRezMS; } } - public int MonitorEventTime { get { return eventMS; } } // This may need to be divided into each event? - public int MonitorBackupTime { get { return backupMS; } } - public int MonitorTerrainTime { get { return terrainMS; } } - public int MonitorLandTime { get { return landMS; } } - public int MonitorLastFrameTick { get { return m_lastFrameTick; } } - - public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } - public bool IsReprioritizationEnabled { get; set; } - public double ReprioritizationInterval { get; set; } - public double RootReprioritizationDistance { get; set; } - public double ChildReprioritizationDistance { get; set; } - - public AgentCircuitManager AuthenticateHandler - { - get { return m_authenticateHandler; } - } - - // an instance to the physics plugin's Scene object. - public PhysicsScene PhysicsScene - { - get { return m_sceneGraph.PhysicsScene; } - set - { - // If we're not doing the initial set - // Then we've got to remove the previous - // event handler - if (PhysicsScene != null && PhysicsScene.SupportsNINJAJoints) - { - PhysicsScene.OnJointMoved -= jointMoved; - PhysicsScene.OnJointDeactivated -= jointDeactivated; - PhysicsScene.OnJointErrorMessage -= jointErrorMessage; - } - - m_sceneGraph.PhysicsScene = value; - - if (PhysicsScene != null && m_sceneGraph.PhysicsScene.SupportsNINJAJoints) - { - // register event handlers to respond to joint movement/deactivation - PhysicsScene.OnJointMoved += jointMoved; - PhysicsScene.OnJointDeactivated += jointDeactivated; - PhysicsScene.OnJointErrorMessage += jointErrorMessage; - } - } - } - - public string DefaultScriptEngine - { - get { return m_defaultScriptEngine; } - } - - public EntityManager Entities - { - get { return m_sceneGraph.Entities; } - } - - - // used in sequence see: SpawnPoint() - private int m_SpawnPoint; - // can be closest/random/sequence - public string SpawnPointRouting - { - get; - private set; - } - // allow landmarks to pass - public bool TelehubAllowLandmarks - { - get; - private set; - } - - #endregion Properties - - #region Constructors - - public Scene(RegionInfo regInfo, AgentCircuitManager authen, PhysicsScene physicsScene, - SceneCommunicationService sceneGridService, - ISimulationDataService simDataService, IEstateDataService estateDataService, - IConfigSource config, string simulatorVersion) - : this(regInfo, physicsScene) - { - m_config = config; - MinFrameTicks = 89; - MinMaintenanceTicks = 1000; - SeeIntoRegion = true; - - Random random = new Random(); - - m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4); - m_authenticateHandler = authen; - m_sceneGridService = sceneGridService; - m_SimulationDataService = simDataService; - m_EstateDataService = estateDataService; - - m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); - m_asyncSceneObjectDeleter.Enabled = true; - - m_asyncInventorySender = new AsyncInventorySender(this); - - #region Region Settings - - // Load region settings - // LoadRegionSettings creates new region settings in persistence if they don't already exist for this region. - // However, in this case, the default textures are not set in memory properly, so we need to do it here and - // resave. - // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new - // region is set up and avoid these gyrations. - RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID); - m_extraSettings = simDataService.GetExtra(RegionInfo.RegionID); - - bool updatedTerrainTextures = false; - if (rs.TerrainTexture1 == UUID.Zero) - { - rs.TerrainTexture1 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_1; - updatedTerrainTextures = true; - } - - if (rs.TerrainTexture2 == UUID.Zero) - { - rs.TerrainTexture2 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_2; - updatedTerrainTextures = true; - } - - if (rs.TerrainTexture3 == UUID.Zero) - { - rs.TerrainTexture3 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_3; - updatedTerrainTextures = true; - } - - if (rs.TerrainTexture4 == UUID.Zero) - { - rs.TerrainTexture4 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_4; - updatedTerrainTextures = true; - } - - if (updatedTerrainTextures) - rs.Save(); - - RegionInfo.RegionSettings = rs; - - if (estateDataService != null) - RegionInfo.EstateSettings = estateDataService.LoadEstateSettings(RegionInfo.RegionID, false); - - #endregion Region Settings - - //Bind Storage Manager functions to some land manager functions for this scene - EventManager.OnLandObjectAdded += - new EventManager.LandObjectAdded(simDataService.StoreLandObject); - EventManager.OnLandObjectRemoved += - new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); - - RegisterDefaultSceneEvents(); - - // XXX: Don't set the public property since we don't want to activate here. This needs to be handled - // better in the future. - m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts; - - PhysicsEnabled = !RegionInfo.RegionSettings.DisablePhysics; - - m_simulatorVersion = simulatorVersion + " (" + Util.GetRuntimeInformation() + ")"; - - #region Region Config - - // Region config overrides global config - // - if (m_config.Configs["Startup"] != null) - { - IConfig startupConfig = m_config.Configs["Startup"]; - - StartDisabled = startupConfig.GetBoolean("StartDisabled", false); - - m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); - UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); - if (!UseBackup) - m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); - - //Animation states - m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); + public ISimulationService SimulationService + { + get + { + if (m_simulationService == null) + m_simulationService = RequestModuleInterface(); - SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion); + return m_simulationService; + } + } - MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); + public IAuthenticationService AuthenticationService + { + get + { + if (m_AuthenticationService == null) + m_AuthenticationService = RequestModuleInterface(); + return m_AuthenticationService; + } + } - PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); - CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); + public IPresenceService PresenceService + { + get + { + if (m_PresenceService == null) + m_PresenceService = RequestModuleInterface(); + return m_PresenceService; + } + } - m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); - if (RegionInfo.NonphysPrimMin > 0) + public IUserAccountService UserAccountService + { + get { - m_minNonphys = RegionInfo.NonphysPrimMin; + if (m_UserAccountService == null) + m_UserAccountService = RequestModuleInterface(); + return m_UserAccountService; } + } - m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); - if (RegionInfo.NonphysPrimMax > 0) + public IAvatarService AvatarService + { + get { - m_maxNonphys = RegionInfo.NonphysPrimMax; + if (m_AvatarService == null) + m_AvatarService = RequestModuleInterface(); + return m_AvatarService; + } + } + + public IGridUserService GridUserService + { + get + { + if (m_GridUserService == null) + m_GridUserService = RequestModuleInterface(); + return m_GridUserService; + } + } + + public IAttachmentsModule AttachmentsModule { get; set; } + public IEntityTransferModule EntityTransferModule { get; private set; } + public IAgentAssetTransactions AgentTransactionsModule { get; private set; } + public IUserManagement UserManagementModule { get; private set; } + + public IAvatarFactoryModule AvatarFactory + { + get { return m_AvatarFactory; } + } + + public ICapabilitiesModule CapsModule + { + get { return m_capsModule; } + } + + public int MonitorFrameTime { get { return frameMS; } } + public int MonitorPhysicsUpdateTime { get { return physicsMS; } } + public int MonitorPhysicsSyncTime { get { return physicsMS2; } } + public int MonitorOtherTime { get { return otherMS; } } + public int MonitorTempOnRezTime { get { return tempOnRezMS; } } + public int MonitorEventTime { get { return eventMS; } } // This may need to be divided into each event? + public int MonitorBackupTime { get { return backupMS; } } + public int MonitorTerrainTime { get { return terrainMS; } } + public int MonitorLandTime { get { return landMS; } } + public int MonitorLastFrameTick { get { return m_lastFrameTick; } } + + public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } + public bool IsReprioritizationEnabled { get; set; } + public double ReprioritizationInterval { get; set; } + public double RootReprioritizationDistance { get; set; } + public double ChildReprioritizationDistance { get; set; } + + public AgentCircuitManager AuthenticateHandler + { + get { return m_authenticateHandler; } + } + + // an instance to the physics plugin's Scene object. + public PhysicsScene PhysicsScene + { + get { return m_sceneGraph.PhysicsScene; } + set + { + // If we're not doing the initial set + // Then we've got to remove the previous + // event handler + if (PhysicsScene != null && PhysicsScene.SupportsNINJAJoints) + { + PhysicsScene.OnJointMoved -= jointMoved; + PhysicsScene.OnJointDeactivated -= jointDeactivated; + PhysicsScene.OnJointErrorMessage -= jointErrorMessage; + } + + m_sceneGraph.PhysicsScene = value; + + if (PhysicsScene != null && m_sceneGraph.PhysicsScene.SupportsNINJAJoints) + { + // register event handlers to respond to joint movement/deactivation + PhysicsScene.OnJointMoved += jointMoved; + PhysicsScene.OnJointDeactivated += jointDeactivated; + PhysicsScene.OnJointErrorMessage += jointErrorMessage; + } } + } + + public string DefaultScriptEngine + { + get { return m_defaultScriptEngine; } + } + + public EntityManager Entities + { + get { return m_sceneGraph.Entities; } + } + + + // used in sequence see: SpawnPoint() + private int m_SpawnPoint; + // can be closest/random/sequence + public string SpawnPointRouting + { + get; + private set; + } + // allow landmarks to pass + public bool TelehubAllowLandmarks + { + get; + private set; + } + + #endregion Properties + + #region Constructors + + public Scene(RegionInfo regInfo, AgentCircuitManager authen, PhysicsScene physicsScene, + SceneCommunicationService sceneGridService, + ISimulationDataService simDataService, IEstateDataService estateDataService, + IConfigSource config, string simulatorVersion) + : this(regInfo, physicsScene) + { + m_config = config; + MinFrameTicks = 89; + MinMaintenanceTicks = 1000; + SeeIntoRegion = true; + + Random random = new Random(); + + m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4); + m_authenticateHandler = authen; + m_sceneGridService = sceneGridService; + m_SimulationDataService = simDataService; + m_EstateDataService = estateDataService; + + m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); + m_asyncSceneObjectDeleter.Enabled = true; + + m_asyncInventorySender = new AsyncInventorySender(this); + + #region Region Settings + + // Load region settings + // LoadRegionSettings creates new region settings in persistence if they don't already exist for this region. + // However, in this case, the default textures are not set in memory properly, so we need to do it here and + // resave. + // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new + // region is set up and avoid these gyrations. + RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID); + m_extraSettings = simDataService.GetExtra(RegionInfo.RegionID); - m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys); - if (RegionInfo.PhysPrimMin > 0) + bool updatedTerrainTextures = false; + if (rs.TerrainTexture1 == UUID.Zero) { - m_minPhys = RegionInfo.PhysPrimMin; + rs.TerrainTexture1 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_1; + updatedTerrainTextures = true; } - m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); - if (RegionInfo.PhysPrimMax > 0) + if (rs.TerrainTexture2 == UUID.Zero) { - m_maxPhys = RegionInfo.PhysPrimMax; + rs.TerrainTexture2 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_2; + updatedTerrainTextures = true; } - // Here, if clamping is requested in either global or - // local config, it will be used - // - m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize); - if (RegionInfo.ClampPrimSize) + if (rs.TerrainTexture3 == UUID.Zero) { - m_clampPrimSize = true; + rs.TerrainTexture3 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_3; + updatedTerrainTextures = true; } - m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); - if (RegionInfo.LinksetCapacity > 0) + if (rs.TerrainTexture4 == UUID.Zero) { - m_linksetCapacity = RegionInfo.LinksetCapacity; + rs.TerrainTexture4 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_4; + updatedTerrainTextures = true; } - m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); - m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); - m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); - m_dontPersistBefore = - startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); - m_dontPersistBefore *= 10000000; - m_persistAfter = - startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); - m_persistAfter *= 10000000; + if (updatedTerrainTextures) + rs.Save(); - m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); + RegionInfo.RegionSettings = rs; - SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); - TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); + if (estateDataService != null) + RegionInfo.EstateSettings = estateDataService.LoadEstateSettings(RegionInfo.RegionID, false); - m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); + #endregion Region Settings - string[] possibleMapConfigSections = new string[] { "Map", "Startup" }; + //Bind Storage Manager functions to some land manager functions for this scene + EventManager.OnLandObjectAdded += + new EventManager.LandObjectAdded(simDataService.StoreLandObject); + EventManager.OnLandObjectRemoved += + new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); - m_generateMaptiles - = Util.GetConfigVarFromSections(config, "GenerateMaptiles", possibleMapConfigSections, true); + RegisterDefaultSceneEvents(); - if (m_generateMaptiles) - { - int maptileRefresh = Util.GetConfigVarFromSections(config, "MaptileRefresh", possibleMapConfigSections, 0); - m_log.InfoFormat("[SCENE]: Region {0}, WORLD MAP refresh time set to {1} seconds", RegionInfo.RegionName, maptileRefresh); - if (maptileRefresh != 0) - { - m_mapGenerationTimer.Interval = maptileRefresh * 1000; - m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister; - m_mapGenerationTimer.AutoReset = true; - m_mapGenerationTimer.Start(); - } - } - else - { - string tile - = Util.GetConfigVarFromSections( - config, "MaptileStaticUUID", possibleMapConfigSections, UUID.Zero.ToString()); + // XXX: Don't set the public property since we don't want to activate here. This needs to be handled + // better in the future. + m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts; - UUID tileID; + PhysicsEnabled = !RegionInfo.RegionSettings.DisablePhysics; - if (tile != UUID.Zero.ToString() && UUID.TryParse(tile, out tileID)) - { - RegionInfo.RegionSettings.TerrainImageID = tileID; - } - else - { - RegionInfo.RegionSettings.TerrainImageID = RegionInfo.MaptileStaticUUID; - m_log.InfoFormat("[SCENE]: Region {0}, maptile set to {1}", RegionInfo.RegionName, RegionInfo.MaptileStaticUUID.ToString()); - } - } + m_simulatorVersion = simulatorVersion + " (" + Util.GetRuntimeInformation() + ")"; + + #region Region Config - string[] possibleAccessControlConfigSections = new string[] { "AccessControl", "Startup" }; + // Region config overrides global config + // + if (m_config.Configs["Startup"] != null) + { + IConfig startupConfig = m_config.Configs["Startup"]; + + StartDisabled = startupConfig.GetBoolean("StartDisabled", false); + + m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); + UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); + if (!UseBackup) + m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); + + //Animation states + m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); + + SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion); + + MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); + + PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); + CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); + + m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); + if (RegionInfo.NonphysPrimMin > 0) + { + m_minNonphys = RegionInfo.NonphysPrimMin; + } + + m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); + if (RegionInfo.NonphysPrimMax > 0) + { + m_maxNonphys = RegionInfo.NonphysPrimMax; + } + + m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys); + if (RegionInfo.PhysPrimMin > 0) + { + m_minPhys = RegionInfo.PhysPrimMin; + } + + m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); + if (RegionInfo.PhysPrimMax > 0) + { + m_maxPhys = RegionInfo.PhysPrimMax; + } + + // Here, if clamping is requested in either global or + // local config, it will be used + // + m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize); + if (RegionInfo.ClampPrimSize) + { + m_clampPrimSize = true; + } + + m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); + if (RegionInfo.LinksetCapacity > 0) + { + m_linksetCapacity = RegionInfo.LinksetCapacity; + } + + m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); + m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); + m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); + m_dontPersistBefore = + startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); + m_dontPersistBefore *= 10000000; + m_persistAfter = + startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); + m_persistAfter *= 10000000; + + m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); + + SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); + TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); + + m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); + + string[] possibleMapConfigSections = new string[] { "Map", "Startup" }; + + m_generateMaptiles + = Util.GetConfigVarFromSections(config, "GenerateMaptiles", possibleMapConfigSections, true); - string grant + if (m_generateMaptiles) + { + int maptileRefresh = Util.GetConfigVarFromSections(config, "MaptileRefresh", possibleMapConfigSections, 0); + m_log.InfoFormat("[SCENE]: Region {0}, WORLD MAP refresh time set to {1} seconds", RegionInfo.RegionName, maptileRefresh); + if (maptileRefresh != 0) + { + m_mapGenerationTimer.Interval = maptileRefresh * 1000; + m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister; + m_mapGenerationTimer.AutoReset = true; + m_mapGenerationTimer.Start(); + } + } + else + { + string tile + = Util.GetConfigVarFromSections( + config, "MaptileStaticUUID", possibleMapConfigSections, UUID.Zero.ToString()); + + UUID tileID; + + if (tile != UUID.Zero.ToString() && UUID.TryParse(tile, out tileID)) + { + RegionInfo.RegionSettings.TerrainImageID = tileID; + } + else + { + RegionInfo.RegionSettings.TerrainImageID = RegionInfo.MaptileStaticUUID; + m_log.InfoFormat("[SCENE]: Region {0}, maptile set to {1}", RegionInfo.RegionName, RegionInfo.MaptileStaticUUID.ToString()); + } + } + + string[] possibleAccessControlConfigSections = new string[] { "AccessControl", "Startup" }; + + string grant = Util.GetConfigVarFromSections( - config, "AllowedClients", possibleAccessControlConfigSections, ""); + config, "AllowedClients", possibleAccessControlConfigSections, ""); - if (grant.Length > 0) - { - foreach (string viewer in grant.Split('|')) - { - m_AllowedViewers.Add(viewer.Trim().ToLower()); - } - } + if (grant.Length > 0) + { + foreach (string viewer in grant.Split('|')) + { + m_AllowedViewers.Add(viewer.Trim().ToLower()); + } + } - grant + grant = Util.GetConfigVarFromSections( - config, "BannedClients", possibleAccessControlConfigSections, ""); + config, "BannedClients", possibleAccessControlConfigSections, ""); - if (grant.Length > 0) - { - foreach (string viewer in grant.Split('|')) - { - m_BannedViewers.Add(viewer.Trim().ToLower()); - } - } + if (grant.Length > 0) + { + foreach (string viewer in grant.Split('|')) + { + m_BannedViewers.Add(viewer.Trim().ToLower()); + } + } - if (startupConfig.Contains("MinFrameTime")) - MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000); + if (startupConfig.Contains("MinFrameTime")) + MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000); - m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup); - m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); - m_update_entitymovement = startupConfig.GetInt("UpdateEntityMovementEveryNFrames", m_update_entitymovement); - m_update_events = startupConfig.GetInt("UpdateEventsEveryNFrames", m_update_events); - m_update_objects = startupConfig.GetInt("UpdateObjectsEveryNFrames", m_update_objects); - m_update_physics = startupConfig.GetInt("UpdatePhysicsEveryNFrames", m_update_physics); - m_update_presences = startupConfig.GetInt("UpdateAgentsEveryNFrames", m_update_presences); - m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain); - m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning); - } + m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup); + m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); + m_update_entitymovement = startupConfig.GetInt("UpdateEntityMovementEveryNFrames", m_update_entitymovement); + m_update_events = startupConfig.GetInt("UpdateEventsEveryNFrames", m_update_events); + m_update_objects = startupConfig.GetInt("UpdateObjectsEveryNFrames", m_update_objects); + m_update_physics = startupConfig.GetInt("UpdatePhysicsEveryNFrames", m_update_physics); + m_update_presences = startupConfig.GetInt("UpdateAgentsEveryNFrames", m_update_presences); + m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain); + m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning); + } - // FIXME: Ultimately this should be in a module. - SendPeriodicAppearanceUpdates = false; + // FIXME: Ultimately this should be in a module. + SendPeriodicAppearanceUpdates = false; - IConfig appearanceConfig = m_config.Configs["Appearance"]; - if (appearanceConfig != null) - { - SendPeriodicAppearanceUpdates + IConfig appearanceConfig = m_config.Configs["Appearance"]; + if (appearanceConfig != null) + { + SendPeriodicAppearanceUpdates = appearanceConfig.GetBoolean("ResendAppearanceUpdates", SendPeriodicAppearanceUpdates); - } - - #endregion Region Config - - IConfig entityTransferConfig = m_config.Configs["EntityTransfer"]; - if (entityTransferConfig != null) - { - AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing); - } - - #region Interest Management + } - IConfig interestConfig = m_config.Configs["InterestManagement"]; - if (interestConfig != null) - { - string update_prioritization_scheme = interestConfig.GetString("UpdatePrioritizationScheme", "Time").Trim().ToLower(); + #endregion Region Config - try + IConfig entityTransferConfig = m_config.Configs["EntityTransfer"]; + if (entityTransferConfig != null) { - UpdatePrioritizationScheme = (UpdatePrioritizationSchemes)Enum.Parse(typeof(UpdatePrioritizationSchemes), update_prioritization_scheme, true); + AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing); } - catch (Exception) + + #region Interest Management + + IConfig interestConfig = m_config.Configs["InterestManagement"]; + if (interestConfig != null) { - m_log.Warn("[PRIORITIZER]: UpdatePrioritizationScheme was not recognized, setting to default prioritizer Time"); - UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; - } + string update_prioritization_scheme = interestConfig.GetString("UpdatePrioritizationScheme", "Time").Trim().ToLower(); + + try + { + UpdatePrioritizationScheme = (UpdatePrioritizationSchemes)Enum.Parse(typeof(UpdatePrioritizationSchemes), update_prioritization_scheme, true); + } + catch (Exception) + { + m_log.Warn("[PRIORITIZER]: UpdatePrioritizationScheme was not recognized, setting to default prioritizer Time"); + UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; + } - IsReprioritizationEnabled + IsReprioritizationEnabled = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled); - ReprioritizationInterval + ReprioritizationInterval = interestConfig.GetDouble("ReprioritizationInterval", ReprioritizationInterval); - RootReprioritizationDistance + RootReprioritizationDistance = interestConfig.GetDouble("RootReprioritizationDistance", RootReprioritizationDistance); - ChildReprioritizationDistance + ChildReprioritizationDistance = interestConfig.GetDouble("ChildReprioritizationDistance", ChildReprioritizationDistance); - RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod); - ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod); + RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod); + ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod); - RootPositionUpdateTolerance + RootPositionUpdateTolerance = interestConfig.GetFloat("RootPositionUpdateTolerance", RootPositionUpdateTolerance); - RootRotationUpdateTolerance + RootRotationUpdateTolerance = interestConfig.GetFloat("RootRotationUpdateTolerance", RootRotationUpdateTolerance); - RootVelocityUpdateTolerance + RootVelocityUpdateTolerance = interestConfig.GetFloat("RootVelocityUpdateTolerance", RootVelocityUpdateTolerance); - } + } - m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme); + m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme); - #endregion Interest Management + #endregion Interest Management - // The timer used by the Stopwatch class depends on the system hardware and operating system; inform - // if the timer is based on a high-resolution performance counter or based on the system timer; - // the performance counter will provide a more precise time than the system timer - if (Stopwatch.IsHighResolution) + // The timer used by the Stopwatch class depends on the system hardware and operating system; inform + // if the timer is based on a high-resolution performance counter or based on the system timer; + // the performance counter will provide a more precise time than the system timer + if (Stopwatch.IsHighResolution) m_log.InfoFormat("[SCENE]: Using high-resolution performance counter for statistics."); - else + else m_log.InfoFormat("[SCENE]: Using system timer for statistics."); - // Acquire the statistics section of the OpenSim.ini file located - // in the bin directory - IConfig statisticsConfig = m_config.Configs["Statistics"]; - - // Confirm that the statistics section existed in the configuration - // file - if (statisticsConfig != null) - { - // Create the StatsReporter using the number of frames to store - // for the frame time statistics, or 10 frames if the config - // file doesn't contain a value - StatsReporter = new SimStatsReporter(this, - statisticsConfig.GetInt("NumberOfFrames", 10)); - } - else - { - // Create a StatsReporter with the current scene and a default - // 10 frames stored for the frame time statistics - StatsReporter = new SimStatsReporter(this); - } - - StatsReporter.OnSendStatsResult += SendSimStatsPackets; - StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; - - } - - public Scene(RegionInfo regInfo, PhysicsScene physicsScene) - : base(regInfo) - { - m_sceneGraph = new SceneGraph(this); - m_sceneGraph.PhysicsScene = physicsScene; - - // If the scene graph has an Unrecoverable error, restart this sim. - // Currently the only thing that causes it to happen is two kinds of specific - // Physics based crashes. - // - // Out of memory - // Operating system has killed the plugin - m_sceneGraph.UnRecoverableError - += () => - { - m_log.ErrorFormat("[SCENE]: Restarting region {0} due to unrecoverable physics crash", Name); - RestartNow(); - }; + // Acquire the statistics section of the OpenSim.ini file located + // in the bin directory + IConfig statisticsConfig = m_config.Configs["Statistics"]; - PhysicalPrims = true; - CollidablePrims = true; - PhysicsEnabled = true; + // Confirm that the statistics section existed in the configuration + // file + if (statisticsConfig != null) + { + // Create the StatsReporter using the number of frames to store + // for the frame time statistics, or 10 frames if the config + // file doesn't contain a value + StatsReporter = new SimStatsReporter(this, + statisticsConfig.GetInt("NumberOfFrames", + m_defaultNumberFramesStored)); + } + else + { + // Create a StatsReporter with the current scene and a default + // 10 frames stored for the frame time statistics + StatsReporter = new SimStatsReporter(this); + } - AllowAvatarCrossing = true; + StatsReporter.OnSendStatsResult += SendSimStatsPackets; + StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; - PeriodicBackup = true; - UseBackup = true; + } - IsReprioritizationEnabled = true; - UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; - ReprioritizationInterval = 5000; + public Scene(RegionInfo regInfo, PhysicsScene physicsScene) + : base(regInfo) + { + m_sceneGraph = new SceneGraph(this); + m_sceneGraph.PhysicsScene = physicsScene; - RootRotationUpdateTolerance = 0.1f; - RootVelocityUpdateTolerance = 0.001f; - RootPositionUpdateTolerance = 0.05f; - RootReprioritizationDistance = 10.0; - ChildReprioritizationDistance = 20.0; + // If the scene graph has an Unrecoverable error, restart this sim. + // Currently the only thing that causes it to happen is two kinds of specific + // Physics based crashes. + // + // Out of memory + // Operating system has killed the plugin + m_sceneGraph.UnRecoverableError + += () => + { + m_log.ErrorFormat("[SCENE]: Restarting region {0} due to unrecoverable physics crash", Name); + RestartNow(); + }; - m_eventManager = new EventManager(); + PhysicalPrims = true; + CollidablePrims = true; + PhysicsEnabled = true; - m_permissions = new ScenePermissions(this); - } + AllowAvatarCrossing = true; - #endregion + PeriodicBackup = true; + UseBackup = true; - #region Startup / Close Methods + IsReprioritizationEnabled = true; + UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; + ReprioritizationInterval = 5000; - /// - /// The scene graph for this scene - /// - /// TODO: Possibly stop other classes being able to manipulate this directly. - public SceneGraph SceneGraph - { - get { return m_sceneGraph; } - } + RootRotationUpdateTolerance = 0.1f; + RootVelocityUpdateTolerance = 0.001f; + RootPositionUpdateTolerance = 0.05f; + RootReprioritizationDistance = 10.0; + ChildReprioritizationDistance = 20.0; - protected virtual void RegisterDefaultSceneEvents() - { - IDialogModule dm = RequestModuleInterface(); + m_eventManager = new EventManager(); - if (dm != null) - m_eventManager.OnPermissionError += dm.SendAlertToUser; + m_permissions = new ScenePermissions(this); + } - m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; - } - - public override string GetSimulatorVersion() - { - return m_simulatorVersion; - } - - /// - /// Process the fact that a neighbouring region has come up. - /// - /// - /// We only add it to the neighbor list if it's within 1 region from here. - /// Agents may have draw distance values that cross two regions though, so - /// we add it to the notify list regardless of distance. We'll check - /// the agent's draw distance before notifying them though. - /// - /// RegionInfo handle for the new region. - /// True after all operations complete, throws exceptions otherwise. - public override void OtherRegionUp(GridRegion otherRegion) - { - if (RegionInfo.RegionHandle != otherRegion.RegionHandle) - { - //// If these are cast to INT because long + negative values + abs returns invalid data - //int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX); - //int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY); - //if (resultX <= 1 && resultY <= 1) - float dist = (float)Math.Max(DefaultDrawDistance, - (float)Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY)); - uint newRegionX, newRegionY, thisRegionX, thisRegionY; - Util.RegionHandleToRegionLoc(otherRegion.RegionHandle, out newRegionX, out newRegionY); - Util.RegionHandleToRegionLoc(RegionInfo.RegionHandle, out thisRegionX, out thisRegionY); - - //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", - // RegionInfo.RegionName, otherRegion.RegionName, newRegionX, newRegionY); - - if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY)) - { - // Let the grid service module know, so this can be cached - m_eventManager.TriggerOnRegionUp(otherRegion); - - try - { - ForEachRootScenePresence(delegate(ScenePresence agent) - { - //agent.ControllingClient.new - //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); - - List old = new List(); - old.Add(otherRegion.RegionHandle); - agent.DropOldNeighbours(old); - if (EntityTransferModule != null && agent.PresenceType != PresenceType.Npc) - EntityTransferModule.EnableChildAgent(agent, otherRegion); - }); - } - catch (NullReferenceException) - { - // This means that we're not booted up completely yet. - // This shouldn't happen too often anymore. - m_log.Error("[SCENE]: Couldn't inform client of regionup because we got a null reference exception"); - } - } - else - { - m_log.InfoFormat( - "[SCENE]: Got notice about far away Region: {0} at ({1}, {2})", - otherRegion.RegionName, otherRegion.RegionLocX, otherRegion.RegionLocY); - } - } - } - - public void AddNeighborRegion(RegionInfo region) - { - lock (m_neighbours) - { - if (!CheckNeighborRegion(region)) - { - m_neighbours.Add(region); - } - } - } - - public bool CheckNeighborRegion(RegionInfo region) - { - bool found = false; - lock (m_neighbours) - { - foreach (RegionInfo reg in m_neighbours) - { - if (reg.RegionHandle == region.RegionHandle) - { - found = true; - break; - } - } - } - return found; - } - - // Alias IncomingHelloNeighbour OtherRegionUp, for now - public GridRegion IncomingHelloNeighbour(RegionInfo neighbour) - { - OtherRegionUp(new GridRegion(neighbour)); - return new GridRegion(RegionInfo); - } - - // This causes the region to restart immediatley. - public void RestartNow() - { - IConfig startupConfig = m_config.Configs["Startup"]; - if (startupConfig != null) - { - if (startupConfig.GetBoolean("InworldRestartShutsDown", false)) - { - MainConsole.Instance.RunCommand("shutdown"); - return; - } - } - - m_log.InfoFormat("[REGION]: Restarting region {0}", Name); - - Close(); - - base.Restart(); - } - - // This is a helper function that notifies root agents in this region that a new sim near them has come up - // This is in the form of a timer because when an instance of OpenSim.exe is started, - // Even though the sims initialize, they don't listen until 'all of the sims are initialized' - // If we tell an agent about a sim that's not listening yet, the agent will not be able to connect to it. - // subsequently the agent will never see the region come back online. - public void RestartNotifyWaitElapsed(object sender, ElapsedEventArgs e) - { - m_restartWaitTimer.Stop(); - lock (m_regionRestartNotifyList) - { - foreach (RegionInfo region in m_regionRestartNotifyList) - { - GridRegion r = new GridRegion(region); - try - { - ForEachRootScenePresence(delegate(ScenePresence agent) - { - if (EntityTransferModule != null && agent.PresenceType != PresenceType.Npc) - EntityTransferModule.EnableChildAgent(agent, r); - }); - } - catch (NullReferenceException) - { - // This means that we're not booted up completely yet. - // This shouldn't happen too often anymore. - } - } - - // Reset list to nothing. - m_regionRestartNotifyList.Clear(); - } - } - - public int GetInaccurateNeighborCount() - { - return m_neighbours.Count; - } - - // This is the method that shuts down the scene. - public override void Close() - { - if (m_shuttingDown) - { - m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name); - return; - } + #endregion - m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); + #region Startup / Close Methods - StatsReporter.Close(); + /// + /// The scene graph for this scene + /// + /// TODO: Possibly stop other classes being able to manipulate this directly. + public SceneGraph SceneGraph + { + get { return m_sceneGraph; } + } - m_restartTimer.Stop(); - m_restartTimer.Close(); + protected virtual void RegisterDefaultSceneEvents() + { + IDialogModule dm = RequestModuleInterface(); - // Kick all ROOT agents with the message, 'The simulator is going down' - ForEachScenePresence(delegate(ScenePresence avatar) - { - avatar.RemoveNeighbourRegion(RegionInfo.RegionHandle); + if (dm != null) + m_eventManager.OnPermissionError += dm.SendAlertToUser; - if (!avatar.IsChildAgent) - avatar.ControllingClient.Kick("The simulator is going down."); + m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; + } + + public override string GetSimulatorVersion() + { + return m_simulatorVersion; + } + + /// + /// Process the fact that a neighbouring region has come up. + /// + /// + /// We only add it to the neighbor list if it's within 1 region from here. + /// Agents may have draw distance values that cross two regions though, so + /// we add it to the notify list regardless of distance. We'll check + /// the agent's draw distance before notifying them though. + /// + /// RegionInfo handle for the new region. + /// True after all operations complete, throws exceptions otherwise. + public override void OtherRegionUp(GridRegion otherRegion) + { + if (RegionInfo.RegionHandle != otherRegion.RegionHandle) + { + //// If these are cast to INT because long + negative values + abs returns invalid data + //int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX); + //int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY); + //if (resultX <= 1 && resultY <= 1) + float dist = (float)Math.Max(DefaultDrawDistance, + (float)Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY)); + uint newRegionX, newRegionY, thisRegionX, thisRegionY; + Util.RegionHandleToRegionLoc(otherRegion.RegionHandle, out newRegionX, out newRegionY); + Util.RegionHandleToRegionLoc(RegionInfo.RegionHandle, out thisRegionX, out thisRegionY); + + //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", + // RegionInfo.RegionName, otherRegion.RegionName, newRegionX, newRegionY); + + if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY)) + { + // Let the grid service module know, so this can be cached + m_eventManager.TriggerOnRegionUp(otherRegion); + + try + { + ForEachRootScenePresence(delegate(ScenePresence agent) + { + //agent.ControllingClient.new + //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); + + List old = new List(); + old.Add(otherRegion.RegionHandle); + agent.DropOldNeighbours(old); + if (EntityTransferModule != null && agent.PresenceType != PresenceType.Npc) + EntityTransferModule.EnableChildAgent(agent, otherRegion); + }); + } + catch (NullReferenceException) + { + // This means that we're not booted up completely yet. + // This shouldn't happen too often anymore. + m_log.Error("[SCENE]: Couldn't inform client of regionup because we got a null reference exception"); + } + } + else + { + m_log.InfoFormat( + "[SCENE]: Got notice about far away Region: {0} at ({1}, {2})", + otherRegion.RegionName, otherRegion.RegionLocX, otherRegion.RegionLocY); + } + } + } + + public void AddNeighborRegion(RegionInfo region) + { + lock (m_neighbours) + { + if (!CheckNeighborRegion(region)) + { + m_neighbours.Add(region); + } + } + } + + public bool CheckNeighborRegion(RegionInfo region) + { + bool found = false; + lock (m_neighbours) + { + foreach (RegionInfo reg in m_neighbours) + { + if (reg.RegionHandle == region.RegionHandle) + { + found = true; + break; + } + } + } + return found; + } + + // Alias IncomingHelloNeighbour OtherRegionUp, for now + public GridRegion IncomingHelloNeighbour(RegionInfo neighbour) + { + OtherRegionUp(new GridRegion(neighbour)); + return new GridRegion(RegionInfo); + } + + // This causes the region to restart immediatley. + public void RestartNow() + { + IConfig startupConfig = m_config.Configs["Startup"]; + if (startupConfig != null) + { + if (startupConfig.GetBoolean("InworldRestartShutsDown", false)) + { + MainConsole.Instance.RunCommand("shutdown"); + return; + } + } - avatar.ControllingClient.SendShutdownConnectionNotice(); - }); + m_log.InfoFormat("[REGION]: Restarting region {0}", Name); - // Stop updating the scene objects and agents. - m_shuttingDown = true; + Close(); - // Wait here, or the kick messages won't actually get to the agents before the scene terminates. - // We also need to wait to avoid a race condition with the scene update loop which might not yet - // have checked ShuttingDown. - Thread.Sleep(500); + base.Restart(); + } - // Stop all client threads. - ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); + // This is a helper function that notifies root agents in this region that a new sim near them has come up + // This is in the form of a timer because when an instance of OpenSim.exe is started, + // Even though the sims initialize, they don't listen until 'all of the sims are initialized' + // If we tell an agent about a sim that's not listening yet, the agent will not be able to connect to it. + // subsequently the agent will never see the region come back online. + public void RestartNotifyWaitElapsed(object sender, ElapsedEventArgs e) + { + m_restartWaitTimer.Stop(); + lock (m_regionRestartNotifyList) + { + foreach (RegionInfo region in m_regionRestartNotifyList) + { + GridRegion r = new GridRegion(region); + try + { + ForEachRootScenePresence(delegate(ScenePresence agent) + { + if (EntityTransferModule != null && agent.PresenceType != PresenceType.Npc) + EntityTransferModule.EnableChildAgent(agent, r); + }); + } + catch (NullReferenceException) + { + // This means that we're not booted up completely yet. + // This shouldn't happen too often anymore. + } + } - m_log.Debug("[SCENE]: Persisting changed objects"); - EventManager.TriggerSceneShuttingDown(this); - Backup(false); - m_sceneGraph.Close(); + // Reset list to nothing. + m_regionRestartNotifyList.Clear(); + } + } - if (!GridService.DeregisterRegion(RegionInfo.RegionID)) - m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); + public int GetInaccurateNeighborCount() + { + return m_neighbours.Count; + } - base.Close(); - - // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence. - // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can - // attempt to reference a null or disposed physics scene. - if (PhysicsScene != null) - { - PhysicsScene phys = PhysicsScene; - // remove the physics engine from both Scene and SceneGraph - PhysicsScene = null; - phys.Dispose(); - phys = null; - } - } - - public override void Start() - { - Start(true); - } - - /// - /// Start the scene - /// - /// - /// Start the scripts within the scene. - /// - public void Start(bool startScripts) - { - if (IsRunning) - return; + // This is the method that shuts down the scene. + public override void Close() + { + if (m_shuttingDown) + { + m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name); + return; + } - m_isRunning = true; - m_active = true; - - // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); - if (m_heartbeatThread != null) - { - m_heartbeatThread.Abort(); - m_heartbeatThread = null; - } - - m_heartbeatThread - = WorkManager.StartThread( - Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); - - StartScripts(); - } - - /// - /// Sets up references to modules required by the scene - /// - public void SetModuleInterfaces() - { - m_xmlrpcModule = RequestModuleInterface(); - m_worldCommModule = RequestModuleInterface(); - XferManager = RequestModuleInterface(); - m_AvatarFactory = RequestModuleInterface(); - AttachmentsModule = RequestModuleInterface(); - m_serialiser = RequestModuleInterface(); - m_dialogModule = RequestModuleInterface(); - m_capsModule = RequestModuleInterface(); - EntityTransferModule = RequestModuleInterface(); - m_groupsModule = RequestModuleInterface(); - AgentTransactionsModule = RequestModuleInterface(); - UserManagementModule = RequestModuleInterface(); - } - - #endregion - - #region Update Methods - - /// - /// Activate the various loops necessary to continually update the scene. - /// - private void Heartbeat() - { - m_eventManager.TriggerOnRegionStarted(this); - - // The first frame can take a very long time due to physics actors being added on startup. Therefore, - // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false - // alarms for scenes with many objects. - Update(1); - - WorkManager.StartThread( - Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); - - Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; - m_lastFrameTick = Util.EnvironmentTickCount(); - - if (UpdateOnTimer) - { - m_sceneUpdateTimer = new Timer(MinFrameTicks); - m_sceneUpdateTimer.AutoReset = true; - m_sceneUpdateTimer.Elapsed += Update; - m_sceneUpdateTimer.Start(); - } - else - { - Thread.CurrentThread.Priority = ThreadPriority.Highest; - Update(-1); - Watchdog.RemoveThread(); - m_isRunning = false; - } - } + m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); - private volatile bool m_isTimerUpdateRunning; + StatsReporter.Close(); - private void Update(object sender, ElapsedEventArgs e) - { - if (m_isTimerUpdateRunning) - return; + m_restartTimer.Stop(); + m_restartTimer.Close(); - m_isTimerUpdateRunning = true; + // Kick all ROOT agents with the message, 'The simulator is going down' + ForEachScenePresence(delegate(ScenePresence avatar) + { + avatar.RemoveNeighbourRegion(RegionInfo.RegionHandle); - // If the last frame did not complete on time, then immediately start the next update on the same thread - // and ignore further timed updates until we have a frame that had spare time. - while (!Update(1) && Active) { } + if (!avatar.IsChildAgent) + avatar.ControllingClient.Kick("The simulator is going down."); - if (!Active || m_shuttingDown) - { - m_sceneUpdateTimer.Stop(); - m_sceneUpdateTimer = null; - m_isRunning = false; - } + avatar.ControllingClient.SendShutdownConnectionNotice(); + }); - m_isTimerUpdateRunning = false; - } + // Stop updating the scene objects and agents. + m_shuttingDown = true; - private void Maintenance() - { - DoMaintenance(-1); + // Wait here, or the kick messages won't actually get to the agents before the scene terminates. + // We also need to wait to avoid a race condition with the scene update loop which might not yet + // have checked ShuttingDown. + Thread.Sleep(500); - Watchdog.RemoveThread(); - } + // Stop all client threads. + ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); - public void DoMaintenance(int runs) - { - long? endRun = null; - int runtc, tmpMS; - int previousMaintenanceTick; + m_log.Debug("[SCENE]: Persisting changed objects"); + EventManager.TriggerSceneShuttingDown(this); + Backup(false); + m_sceneGraph.Close(); - if (runs >= 0) - endRun = MaintenanceRun + runs; + if (!GridService.DeregisterRegion(RegionInfo.RegionID)) + m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); - List coarseLocations; - List avatarUUIDs; + base.Close(); - while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) - { - runtc = Util.EnvironmentTickCount(); - ++MaintenanceRun; + // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence. + // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can + // attempt to reference a null or disposed physics scene. + if (PhysicsScene != null) + { + PhysicsScene phys = PhysicsScene; + // remove the physics engine from both Scene and SceneGraph + PhysicsScene = null; + phys.Dispose(); + phys = null; + } + } + + public override void Start() + { + Start(true); + } + + /// + /// Start the scene + /// + /// + /// Start the scripts within the scene. + /// + public void Start(bool startScripts) + { + if (IsRunning) + return; - // m_log.DebugFormat("[SCENE]: Maintenance run {0} in {1}", MaintenanceRun, Name); + m_isRunning = true; + m_active = true; + + // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); + if (m_heartbeatThread != null) + { + m_heartbeatThread.Abort(); + m_heartbeatThread = null; + } + + m_heartbeatThread + = WorkManager.StartThread( + Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); + + StartScripts(); + } + + /// + /// Sets up references to modules required by the scene + /// + public void SetModuleInterfaces() + { + m_xmlrpcModule = RequestModuleInterface(); + m_worldCommModule = RequestModuleInterface(); + XferManager = RequestModuleInterface(); + m_AvatarFactory = RequestModuleInterface(); + AttachmentsModule = RequestModuleInterface(); + m_serialiser = RequestModuleInterface(); + m_dialogModule = RequestModuleInterface(); + m_capsModule = RequestModuleInterface(); + EntityTransferModule = RequestModuleInterface(); + m_groupsModule = RequestModuleInterface(); + AgentTransactionsModule = RequestModuleInterface(); + UserManagementModule = RequestModuleInterface(); + } + + #endregion + + #region Update Methods + + /// + /// Activate the various loops necessary to continually update the scene. + /// + private void Heartbeat() + { + m_eventManager.TriggerOnRegionStarted(this); + + // The first frame can take a very long time due to physics actors being added on startup. Therefore, + // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false + // alarms for scenes with many objects. + Update(1); + + WorkManager.StartThread( + Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); + + Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; + m_lastFrameTick = Util.EnvironmentTickCount(); - // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) - if (MaintenanceRun % (m_update_coarse_locations / 10) == 0) + if (UpdateOnTimer) { - SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); - // Send coarse locations to clients - ForEachScenePresence(delegate(ScenePresence presence) - { - presence.SendCoarseLocations(coarseLocations, avatarUUIDs); - }); + m_sceneUpdateTimer = new Timer(MinFrameTicks); + m_sceneUpdateTimer.AutoReset = true; + m_sceneUpdateTimer.Elapsed += Update; + m_sceneUpdateTimer.Start(); } - - if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0) + else { - // m_log.DebugFormat("[SCENE]: Sending periodic appearance updates"); - - if (AvatarFactory != null) - { - ForEachRootScenePresence(sp => AvatarFactory.SendAppearance(sp.UUID)); - } + Thread.CurrentThread.Priority = ThreadPriority.Highest; + Update(-1); + Watchdog.RemoveThread(); + m_isRunning = false; } + } - // Delete temp-on-rez stuff - if (MaintenanceRun % m_update_temp_cleaning == 0 && !m_cleaningTemps) - { - // m_log.DebugFormat("[SCENE]: Running temp-on-rez cleaning in {0}", Name); - tmpMS = Util.EnvironmentTickCount(); - m_cleaningTemps = true; + private volatile bool m_isTimerUpdateRunning; + + private void Update(object sender, ElapsedEventArgs e) + { + if (m_isTimerUpdateRunning) + return; + + m_isTimerUpdateRunning = true; - WorkManager.RunInThread( - delegate { CleanTempObjects(); m_cleaningTemps = false; }, - null, - string.Format("CleanTempObjects ({0})", Name)); + // If the last frame did not complete on time, then immediately start the next update on the same thread + // and ignore further timed updates until we have a frame that had spare time. + while (!Update(1) && Active) { } - tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS); + if (!Active || m_shuttingDown) + { + m_sceneUpdateTimer.Stop(); + m_sceneUpdateTimer = null; + m_isRunning = false; } - Watchdog.UpdateThread(); + m_isTimerUpdateRunning = false; + } - previousMaintenanceTick = m_lastMaintenanceTick; - m_lastMaintenanceTick = Util.EnvironmentTickCount(); - runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); - runtc = MinMaintenanceTicks - runtc; + private void Maintenance() + { + DoMaintenance(-1); - if (runtc > 0) - m_maintenanceWaitEvent.WaitOne(runtc); + Watchdog.RemoveThread(); + } - // Optionally warn if a frame takes double the amount of time that it should. - if (DebugUpdates - && Util.EnvironmentTickCountSubtract( - m_lastMaintenanceTick, previousMaintenanceTick) > MinMaintenanceTicks * 2) - m_log.WarnFormat( - "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", - Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), - MinMaintenanceTicks, - RegionInfo.RegionName); - } - } + public void DoMaintenance(int runs) + { + long? endRun = null; + int runtc, tmpMS; + int previousMaintenanceTick; - public override bool Update(int frames) - { - long? endFrame = null; + if (runs >= 0) + endRun = MaintenanceRun + runs; - if (frames >= 0) + List coarseLocations; + List avatarUUIDs; + + while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) + { + runtc = Util.EnvironmentTickCount(); + ++MaintenanceRun; + + // m_log.DebugFormat("[SCENE]: Maintenance run {0} in {1}", MaintenanceRun, Name); + + // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) + if (MaintenanceRun % (m_update_coarse_locations / 10) == 0) + { + SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); + // Send coarse locations to clients + ForEachScenePresence(delegate(ScenePresence presence) + { + presence.SendCoarseLocations(coarseLocations, avatarUUIDs); + }); + } + + if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0) + { + // m_log.DebugFormat("[SCENE]: Sending periodic appearance updates"); + + if (AvatarFactory != null) + { + ForEachRootScenePresence(sp => AvatarFactory.SendAppearance(sp.UUID)); + } + } + + // Delete temp-on-rez stuff + if (MaintenanceRun % m_update_temp_cleaning == 0 && !m_cleaningTemps) + { + // m_log.DebugFormat("[SCENE]: Running temp-on-rez cleaning in {0}", Name); + tmpMS = Util.EnvironmentTickCount(); + m_cleaningTemps = true; + + WorkManager.RunInThread( + delegate { CleanTempObjects(); m_cleaningTemps = false; }, + null, + string.Format("CleanTempObjects ({0})", Name)); + + tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS); + } + + Watchdog.UpdateThread(); + + previousMaintenanceTick = m_lastMaintenanceTick; + m_lastMaintenanceTick = Util.EnvironmentTickCount(); + runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); + runtc = MinMaintenanceTicks - runtc; + + if (runtc > 0) + m_maintenanceWaitEvent.WaitOne(runtc); + + // Optionally warn if a frame takes double the amount of time that it should. + if (DebugUpdates + && Util.EnvironmentTickCountSubtract( + m_lastMaintenanceTick, previousMaintenanceTick) > MinMaintenanceTicks * 2) + m_log.WarnFormat( + "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", + Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), + MinMaintenanceTicks, + RegionInfo.RegionName); + } + } + + public override bool Update(int frames) + { + long? endFrame = null; + + if (frames >= 0) endFrame = Frame + frames; - float physicsFPS = 0f; - int previousFrameTick, tmpMS; - - // These variables will be used to save the precise frame time using the - // Stopwatch class of Microsoft SDK; the times are recorded at the start - // and end of a parcticular section of code, and then used to calculate - // the frame times, which are the sums of the sections for each given name - double preciseTotalFrameTime = 0.0; - double preciseSimFrameTime = 0.0; - double precisePhysicsFrameTime = 0.0; - Stopwatch totalFrameStopwatch = new Stopwatch(); - Stopwatch simFrameStopwatch = new Stopwatch(); - Stopwatch physicsFrameStopwatch = new Stopwatch(); + float physicsFPS = 0f; + int previousFrameTick, tmpMS; + + // These variables will be used to save the precise frame time using the + // Stopwatch class of Microsoft SDK; the times are recorded at the start + // and end of a parcticular section of code, and then used to calculate + // the frame times, which are the sums of the sections for each given name + double preciseTotalFrameTime = 0.0; + double preciseSimFrameTime = 0.0; + double precisePhysicsFrameTime = 0.0; + Stopwatch totalFrameStopwatch = new Stopwatch(); + Stopwatch simFrameStopwatch = new Stopwatch(); + Stopwatch physicsFrameStopwatch = new Stopwatch(); + + // Begin the stopwatch to keep track of the time that the frame + // started running to determine how long the frame took to complete + totalFrameStopwatch.Start(); + + while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) + { + ++Frame; + + // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); + + agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; + + try + { + EventManager.TriggerRegionHeartbeatStart(this); + + // Apply taints in terrain module to terrain in physics scene + if (Frame % m_update_terrain == 0) + { + tmpMS = Util.EnvironmentTickCount(); + simFrameStopwatch.Start(); + UpdateTerrain(); + + // Get the simulation frame time that the avatar force + // input took + simFrameStopwatch.Stop(); + preciseSimFrameTime = + simFrameStopwatch.Elapsed.TotalMilliseconds; + terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); + } + + // At several points inside the code there was a need to + // create a more precise measurement of time elapsed. This + // led to the addition of variables that have a similar + // function and thus remain tightly connected to their + // original counterparts. However, the original code is + // not receiving comments from our group because we don't + // feel right modifying the code to that degree at this + // point in time, the precise values all begin with the + // keyword precise + + tmpMS = Util.EnvironmentTickCount(); + + // Begin the stopwatch to track the time to prepare physics + physicsFrameStopwatch.Start(); + if (PhysicsEnabled && Frame % m_update_physics == 0) + m_sceneGraph.UpdatePreparePhysics(); + + // Get the time it took to prepare the physics, this + // would report the most precise time that physics was + // running on the machine and should the physics not be + // enabled will report the time it took to check if physics + // was enabled + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds; + physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); + + // Apply any pending avatar force input to the avatar's velocity + tmpMS = Util.EnvironmentTickCount(); + simFrameStopwatch.Restart(); + if (Frame % m_update_entitymovement == 0) + m_sceneGraph.UpdateScenePresenceMovement(); + + // Get the simulation frame time that the avatar force input + // took + simFrameStopwatch.Stop(); + preciseSimFrameTime += + simFrameStopwatch.Elapsed.TotalMilliseconds; + agentMS = Util.EnvironmentTickCountSubtract(tmpMS); + + // Perform the main physics update. This will do the actual work of moving objects and avatars according to their + // velocity + tmpMS = Util.EnvironmentTickCount(); + physicsFrameStopwatch.Restart(); + if (Frame % m_update_physics == 0) + { + if (PhysicsEnabled) + physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds); + + if (SynchronizeScene != null) + SynchronizeScene(this); + } + + // Add the main physics update time to the prepare physics time + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; + physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); + + // Start the stopwatch for the remainder of the simulation + simFrameStopwatch.Restart(); + tmpMS = Util.EnvironmentTickCount(); + + // Check if any objects have reached their targets + CheckAtTargets(); + + // Update SceneObjectGroups that have scheduled themselves for updates + // Objects queue their updates onto all scene presences + if (Frame % m_update_objects == 0) + m_sceneGraph.UpdateObjectGroups(); + + // Run through all ScenePresences looking for updates + // Presence updates and queued object updates for each presence are sent to clients + if (Frame % m_update_presences == 0) + m_sceneGraph.UpdatePresences(); + + agentMS += Util.EnvironmentTickCountSubtract(tmpMS); + + if (Frame % m_update_events == 0) + { + tmpMS = Util.EnvironmentTickCount(); + UpdateEvents(); + eventMS = Util.EnvironmentTickCountSubtract(tmpMS); + } + + if (PeriodicBackup && Frame % m_update_backup == 0) + { + tmpMS = Util.EnvironmentTickCount(); + UpdateStorageBackup(); + backupMS = Util.EnvironmentTickCountSubtract(tmpMS); + } + + //if (Frame % m_update_land == 0) + //{ + // int ldMS = Util.EnvironmentTickCount(); + // UpdateLand(); + // landMS = Util.EnvironmentTickCountSubtract(ldMS); + //} + + if (!LoginsEnabled && Frame == 20) + { + // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); + + // In 99.9% of cases it is a bad idea to manually force garbage collection. However, + // this is a rare case where we know we have just went through a long cycle of heap + // allocations, and there is no more work to be done until someone logs in + GC.Collect(); + + if (!LoginLock) + { + if (!StartDisabled) + { + m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); + LoginsEnabled = true; + } + + m_sceneGridService.InformNeighborsThatRegionisUp( + RequestModuleInterface(), RegionInfo); + + // Region ready should always be set + Ready = true; + } + else + { + // This handles a case of a region having no scripts for the RegionReady module + if (m_sceneGraph.GetActiveScriptsCount() == 0) + { + // In this case, we leave it to the IRegionReadyModule to enable logins + + // LoginLock can currently only be set by a region module implementation. + // If somehow this hasn't been done then the quickest way to bugfix is to see the + // NullReferenceException + IRegionReadyModule rrm = RequestModuleInterface(); + rrm.TriggerRegionReady(this); + } + } + } + } + catch (Exception e) + { + m_log.ErrorFormat( + "[SCENE]: Failed on region {0} with exception {1}{2}", + RegionInfo.RegionName, e.Message, e.StackTrace); + } + + EventManager.TriggerRegionHeartbeatEnd(this); + otherMS = eventMS + backupMS + terrainMS + landMS; + + // Get the elapsed time for the simulation frame + simFrameStopwatch.Stop(); + preciseSimFrameTime += + simFrameStopwatch.Elapsed.TotalMilliseconds; - // Begin the stopwatch to keep track of the time that the frame - // started running to determine how long the frame took to complete - totalFrameStopwatch.Start(); + if (!UpdateOnTimer) + { + Watchdog.UpdateThread(); + + spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick); + + if (spareMS > 0) + m_updateWaitEvent.WaitOne(spareMS); + else + spareMS = 0; + } + else + { + spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); + } + + // Get the total frame time + totalFrameStopwatch.Stop(); + preciseTotalFrameTime = + totalFrameStopwatch.Elapsed.TotalMilliseconds; - while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) - { - ++Frame; + // Restart the stopwatch for the total time of the next frame + totalFrameStopwatch.Restart(); + + previousFrameTick = m_lastFrameTick; + frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); + m_lastFrameTick = Util.EnvironmentTickCount(); + + // if (Frame%m_update_avatars == 0) + // UpdateInWorldTime(); + StatsReporter.AddPhysicsFPS(physicsFPS); + StatsReporter.AddTimeDilation(TimeDilation); + StatsReporter.AddFPS(1); + + StatsReporter.addFrameMS(frameMS); + StatsReporter.addAgentMS(agentMS); + StatsReporter.addPhysicsMS(physicsMS + physicsMS2); + StatsReporter.addOtherMS(otherMS); + StatsReporter.AddSpareMS(spareMS); + StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); + + // Send the correct time values to the stats reporter for the + // frame times + StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime, + preciseSimFrameTime, precisePhysicsFrameTime, 0.0); + + // Send the correct number of frames that the physics library + // has processed to the stats reporter + StatsReporter.addPhysicsFrame(1); + + // Optionally warn if a frame takes double the amount of time that it should. + if (DebugUpdates + && Util.EnvironmentTickCountSubtract( + m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2) + m_log.WarnFormat( + "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", + Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), + MinFrameTicks, + RegionInfo.RegionName); + } + + // Finished updating scene frame, so stop the total frame's Stopwatch + totalFrameStopwatch.Stop(); - // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); + return spareMS >= 0; + } - agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; + public void AddGroupTarget(SceneObjectGroup grp) + { + lock (m_groupsWithTargets) + m_groupsWithTargets[grp.UUID] = grp; + } + public void RemoveGroupTarget(SceneObjectGroup grp) + { + lock (m_groupsWithTargets) + m_groupsWithTargets.Remove(grp.UUID); + } + + private void CheckAtTargets() + { + List objs = null; + + lock (m_groupsWithTargets) + { + if (m_groupsWithTargets.Count != 0) + objs = new List(m_groupsWithTargets.Values); + } + + if (objs != null) + { + foreach (SceneObjectGroup entry in objs) + entry.checkAtTargets(); + } + } + + /// + /// Send out simstats data to all clients + /// + /// Stats on the Simulator's performance + private void SendSimStatsPackets(SimStats stats) + { + ForEachRootClient(delegate(IClientAPI client) + { + client.SendSimStats(stats); + }); + } + + /// + /// Update the terrain if it needs to be updated. + /// + private void UpdateTerrain() + { + EventManager.TriggerTerrainTick(); + } + + /// + /// Back up queued up changes + /// + private void UpdateStorageBackup() + { + if (!m_backingup) + { + m_backingup = true; + WorkManager.RunInThread(o => Backup(false), null, string.Format("BackupWaitCallback ({0})", Name)); + } + } + + /// + /// Sends out the OnFrame event to the modules + /// + private void UpdateEvents() + { + m_eventManager.TriggerOnFrame(); + } + + /// + /// Backup the scene. + /// + /// + /// This acts as the main method of the backup thread. In a regression test whether the backup thread is not + /// running independently this can be invoked directly. + /// + /// + /// If true, then any changes that have not yet been persisted are persisted. If false, + /// then the persistence decision is left to the backup code (in some situations, such as object persistence, + /// it's much more efficient to backup multiple changes at once rather than every single one). + /// + public void Backup(bool forced) + { + lock (m_returns) + { + EventManager.TriggerOnBackup(SimulationDataService, forced); + m_backingup = false; + + foreach (KeyValuePair ret in m_returns) + { + UUID transaction = UUID.Random(); + + GridInstantMessage msg = new GridInstantMessage(); + msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server + msg.toAgentID = new Guid(ret.Key.ToString()); + msg.imSessionID = new Guid(transaction.ToString()); + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.fromAgentName = "Server"; + msg.dialog = (byte)19; // Object msg + msg.fromGroup = false; + msg.offline = (byte)0; + msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; + msg.Position = Vector3.Zero; + msg.RegionID = RegionInfo.RegionID.Guid; + + // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3. + msg.binaryBucket = Util.StringToBytes256("\0"); + if (ret.Value.count > 1) + msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); + else + msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); + + IMessageTransferModule tr = RequestModuleInterface(); + if (tr != null) + tr.SendInstantMessage(msg, delegate(bool success) { }); + } + m_returns.Clear(); + } + } + + /// + /// Synchronous force backup. For deletes and links/unlinks + /// + /// Object to be backed up + public void ForceSceneObjectBackup(SceneObjectGroup group) + { + if (group != null) + { + group.HasGroupChanged = true; + group.ProcessBackup(SimulationDataService, true); + } + } + + /// + /// Tell an agent that their object has been returned. + /// + /// + /// The actual return is handled by the caller. + /// + /// Avatar Unique Id + /// Name of object returned + /// Location of object returned + /// Reasion for object return + public void AddReturn(UUID agentID, string objectName, Vector3 location, string reason) + { + lock (m_returns) + { + if (m_returns.ContainsKey(agentID)) + { + ReturnInfo info = m_returns[agentID]; + info.count++; + m_returns[agentID] = info; + } + else + { + ReturnInfo info = new ReturnInfo(); + info.count = 1; + info.objectName = objectName; + info.location = location; + info.reason = reason; + m_returns[agentID] = info; + } + } + } + + #endregion + + #region Load Terrain + + /// + /// Store the terrain in the persistant data store + /// + public void SaveTerrain() + { + SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); + } + + public void StoreWindlightProfile(RegionLightShareData wl) + { + RegionInfo.WindlightSettings = wl; + SimulationDataService.StoreRegionWindlightSettings(wl); + m_eventManager.TriggerOnSaveNewWindlightProfile(); + } + + public void LoadWindlightProfile() + { + RegionInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(RegionInfo.RegionID); + m_eventManager.TriggerOnSaveNewWindlightProfile(); + } + + /// + /// Loads the World heightmap + /// + public override void LoadWorldMap() + { try { - EventManager.TriggerRegionHeartbeatStart(this); - - // Apply taints in terrain module to terrain in physics scene - if (Frame % m_update_terrain == 0) - { - tmpMS = Util.EnvironmentTickCount(); - simFrameStopwatch.Start(); - UpdateTerrain(); - - // Get the simulation frame time that the avatar force - // input took - simFrameStopwatch.Stop(); - preciseSimFrameTime = - simFrameStopwatch.Elapsed.TotalMilliseconds; - terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); - } - - // At several points inside the code there was a need to - // create a more precise measurement of time elapsed. This - // led to the addition of variables that have a similar - // function and thus remain tightly connected to their - // original counterparts. However, the original code is - // not receiving comments from our group because we don't - // feel right modifying the code to that degree at this - // point in time, the precise values all begin with the - // keyword precise - - tmpMS = Util.EnvironmentTickCount(); - - // Begin the stopwatch to track the time to prepare physics - physicsFrameStopwatch.Start(); - if (PhysicsEnabled && Frame % m_update_physics == 0) - m_sceneGraph.UpdatePreparePhysics(); - - // Get the time it took to prepare the physics, this - // would report the most precise time that physics was - // running on the machine and should the physics not be - // enabled will report the time it took to check if physics - // was enabled - physicsFrameStopwatch.Stop(); - precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds; - physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); - - // Apply any pending avatar force input to the avatar's velocity - tmpMS = Util.EnvironmentTickCount(); - simFrameStopwatch.Restart(); - if (Frame % m_update_entitymovement == 0) - m_sceneGraph.UpdateScenePresenceMovement(); - - // Get the simulation frame time that the avatar force input - // took - simFrameStopwatch.Stop(); - preciseSimFrameTime += - simFrameStopwatch.Elapsed.TotalMilliseconds; - agentMS = Util.EnvironmentTickCountSubtract(tmpMS); - - // Perform the main physics update. This will do the actual work of moving objects and avatars according to their - // velocity - tmpMS = Util.EnvironmentTickCount(); - physicsFrameStopwatch.Restart(); - if (Frame % m_update_physics == 0) - { - if (PhysicsEnabled) - physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds); - - if (SynchronizeScene != null) - SynchronizeScene(this); - } - - // Add the main physics update time to the prepare physics time - physicsFrameStopwatch.Stop(); - precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; - physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); - - // Start the stopwatch for the remainder of the simulation - simFrameStopwatch.Restart(); - tmpMS = Util.EnvironmentTickCount(); - - // Check if any objects have reached their targets - CheckAtTargets(); - - // Update SceneObjectGroups that have scheduled themselves for updates - // Objects queue their updates onto all scene presences - if (Frame % m_update_objects == 0) - m_sceneGraph.UpdateObjectGroups(); - - // Run through all ScenePresences looking for updates - // Presence updates and queued object updates for each presence are sent to clients - if (Frame % m_update_presences == 0) - m_sceneGraph.UpdatePresences(); - - agentMS += Util.EnvironmentTickCountSubtract(tmpMS); - - if (Frame % m_update_events == 0) - { - tmpMS = Util.EnvironmentTickCount(); - UpdateEvents(); - eventMS = Util.EnvironmentTickCountSubtract(tmpMS); - } - - if (PeriodicBackup && Frame % m_update_backup == 0) - { - tmpMS = Util.EnvironmentTickCount(); - UpdateStorageBackup(); - backupMS = Util.EnvironmentTickCountSubtract(tmpMS); - } - - //if (Frame % m_update_land == 0) - //{ - // int ldMS = Util.EnvironmentTickCount(); - // UpdateLand(); - // landMS = Util.EnvironmentTickCountSubtract(ldMS); - //} - - if (!LoginsEnabled && Frame == 20) - { - // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); - - // In 99.9% of cases it is a bad idea to manually force garbage collection. However, - // this is a rare case where we know we have just went through a long cycle of heap - // allocations, and there is no more work to be done until someone logs in - GC.Collect(); - - if (!LoginLock) - { - if (!StartDisabled) - { - m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); - LoginsEnabled = true; - } - - m_sceneGridService.InformNeighborsThatRegionisUp( - RequestModuleInterface(), RegionInfo); - - // Region ready should always be set - Ready = true; - } - else - { - // This handles a case of a region having no scripts for the RegionReady module - if (m_sceneGraph.GetActiveScriptsCount() == 0) - { - // In this case, we leave it to the IRegionReadyModule to enable logins - - // LoginLock can currently only be set by a region module implementation. - // If somehow this hasn't been done then the quickest way to bugfix is to see the - // NullReferenceException - IRegionReadyModule rrm = RequestModuleInterface(); - rrm.TriggerRegionReady(this); - } - } - } + TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); + if (map == null) + { + // This should be in the Terrain module, but it isn't because + // the heightmap is needed _way_ before the modules are initialized... + IConfig terrainConfig = m_config.Configs["Terrain"]; + String m_InitialTerrain = "pinhead-island"; + if (terrainConfig != null) + m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); + + m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); + Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); + + SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); + } + else + { + Heightmap = new TerrainChannel(map); + } + } + catch (IOException e) + { + m_log.WarnFormat( + "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}", + e.Message, e.StackTrace); + + // Non standard region size. If there's an old terrain in the database, it might read past the buffer +#pragma warning disable 0162 + if ((int)Constants.RegionSize != 256) + { + Heightmap = new TerrainChannel(); + + SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); + } } catch (Exception e) { - m_log.ErrorFormat( - "[SCENE]: Failed on region {0} with exception {1}{2}", - RegionInfo.RegionName, e.Message, e.StackTrace); + m_log.WarnFormat( + "[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}", e.Message, e.StackTrace); } + } - EventManager.TriggerRegionHeartbeatEnd(this); - otherMS = eventMS + backupMS + terrainMS + landMS; + /// + /// Register this region with a grid service + /// + /// Thrown if registration of the region itself fails. + public void RegisterRegionWithGrid() + { + m_sceneGridService.SetScene(this); - // Get the elapsed time for the simulation frame - simFrameStopwatch.Stop(); - preciseSimFrameTime += - simFrameStopwatch.Elapsed.TotalMilliseconds; + //// Unfortunately this needs to be here and it can't be async. + //// The map tile image is stored in RegionSettings, but it also needs to be + //// stored in the GridService, because that's what the world map module uses + //// to send the map image UUIDs (of other regions) to the viewer... + if (m_generateMaptiles) + RegenerateMaptile(); - if (!UpdateOnTimer) - { - Watchdog.UpdateThread(); + GridRegion region = new GridRegion(RegionInfo); + string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); + // m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>", + // m_regionName, + // RegionInfo.RegionID, + // RegionInfo.RegionLocX, RegionInfo.RegionLocY, + // RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); + + if (error != String.Empty) + throw new Exception(error); + } - spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick); + #endregion - if (spareMS > 0) - m_updateWaitEvent.WaitOne(spareMS); - else - spareMS = 0; + #region Load Land + + /// + /// Loads all Parcel data from the datastore for region identified by regionID + /// + /// Unique Identifier of the Region to load parcel data for + public void loadAllLandObjectsFromStorage(UUID regionID) + { + m_log.Info("[SCENE]: Loading land objects from storage"); + List landData = SimulationDataService.LoadLandObjects(regionID); + + if (LandChannel != null) + { + if (landData.Count == 0) + { + EventManager.TriggerNoticeNoLandDataFromStorage(); + } + else + { + EventManager.TriggerIncomingLandDataFromStorage(landData); + } } else { - spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); + m_log.Error("[SCENE]: Land Channel is not defined. Cannot load from storage!"); } + } - // Get the total frame time - totalFrameStopwatch.Stop(); - preciseTotalFrameTime = - totalFrameStopwatch.Elapsed.TotalMilliseconds; + #endregion - // Restart the stopwatch for the total time of the next frame - totalFrameStopwatch.Restart(); + #region Primitives Methods - previousFrameTick = m_lastFrameTick; - frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); - m_lastFrameTick = Util.EnvironmentTickCount(); + /// + /// Loads the World's objects + /// + /// + public virtual void LoadPrimsFromStorage(UUID regionID) + { + LoadingPrims = true; + m_log.Info("[SCENE]: Loading objects from datastore"); - // if (Frame%m_update_avatars == 0) - // UpdateInWorldTime(); - StatsReporter.AddPhysicsFPS(physicsFPS); - StatsReporter.AddTimeDilation(TimeDilation); - StatsReporter.AddFPS(1); - - StatsReporter.addFrameMS(frameMS); - StatsReporter.addAgentMS(agentMS); - StatsReporter.addPhysicsMS(physicsMS + physicsMS2); - StatsReporter.addOtherMS(otherMS); - StatsReporter.AddSpareMS(spareMS); - StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); - - // Send the correct time values to the stats reporter for the - // frame times - StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime, - preciseSimFrameTime, precisePhysicsFrameTime, 0.0); - - // Send the correct number of frames that the physics library - // has processed to the stats reporter - StatsReporter.addPhysicsFrame(1); - - // Optionally warn if a frame takes double the amount of time that it should. - if (DebugUpdates - && Util.EnvironmentTickCountSubtract( - m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2) - m_log.WarnFormat( - "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", - Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), - MinFrameTicks, - RegionInfo.RegionName); - } - - // Finished updating scene frame, so stop the total frame's Stopwatch - totalFrameStopwatch.Stop(); - - return spareMS >= 0; - } - - public void AddGroupTarget(SceneObjectGroup grp) - { - lock (m_groupsWithTargets) - m_groupsWithTargets[grp.UUID] = grp; - } + List PrimsFromDB = SimulationDataService.LoadObjects(regionID); - public void RemoveGroupTarget(SceneObjectGroup grp) - { - lock (m_groupsWithTargets) - m_groupsWithTargets.Remove(grp.UUID); - } - - private void CheckAtTargets() - { - List objs = null; - - lock (m_groupsWithTargets) - { - if (m_groupsWithTargets.Count != 0) - objs = new List(m_groupsWithTargets.Values); - } - - if (objs != null) - { - foreach (SceneObjectGroup entry in objs) - entry.checkAtTargets(); - } - } - - /// - /// Send out simstats data to all clients - /// - /// Stats on the Simulator's performance - private void SendSimStatsPackets(SimStats stats) - { - ForEachRootClient(delegate(IClientAPI client) - { - client.SendSimStats(stats); - }); - } - - /// - /// Update the terrain if it needs to be updated. - /// - private void UpdateTerrain() - { - EventManager.TriggerTerrainTick(); - } - - /// - /// Back up queued up changes - /// - private void UpdateStorageBackup() - { - if (!m_backingup) - { - m_backingup = true; - WorkManager.RunInThread(o => Backup(false), null, string.Format("BackupWaitCallback ({0})", Name)); - } - } - - /// - /// Sends out the OnFrame event to the modules - /// - private void UpdateEvents() - { - m_eventManager.TriggerOnFrame(); - } - - /// - /// Backup the scene. - /// - /// - /// This acts as the main method of the backup thread. In a regression test whether the backup thread is not - /// running independently this can be invoked directly. - /// - /// - /// If true, then any changes that have not yet been persisted are persisted. If false, - /// then the persistence decision is left to the backup code (in some situations, such as object persistence, - /// it's much more efficient to backup multiple changes at once rather than every single one). - /// - public void Backup(bool forced) - { - lock (m_returns) - { - EventManager.TriggerOnBackup(SimulationDataService, forced); - m_backingup = false; - - foreach (KeyValuePair ret in m_returns) - { - UUID transaction = UUID.Random(); - - GridInstantMessage msg = new GridInstantMessage(); - msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server - msg.toAgentID = new Guid(ret.Key.ToString()); - msg.imSessionID = new Guid(transaction.ToString()); - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - msg.fromAgentName = "Server"; - msg.dialog = (byte)19; // Object msg - msg.fromGroup = false; - msg.offline = (byte)0; - msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; - msg.Position = Vector3.Zero; - msg.RegionID = RegionInfo.RegionID.Guid; - - // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3. - msg.binaryBucket = Util.StringToBytes256("\0"); - if (ret.Value.count > 1) - msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); - else - msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); - - IMessageTransferModule tr = RequestModuleInterface(); - if (tr != null) - tr.SendInstantMessage(msg, delegate(bool success) { }); - } - m_returns.Clear(); - } - } - - /// - /// Synchronous force backup. For deletes and links/unlinks - /// - /// Object to be backed up - public void ForceSceneObjectBackup(SceneObjectGroup group) - { - if (group != null) - { - group.HasGroupChanged = true; - group.ProcessBackup(SimulationDataService, true); - } - } - - /// - /// Tell an agent that their object has been returned. - /// - /// - /// The actual return is handled by the caller. - /// - /// Avatar Unique Id - /// Name of object returned - /// Location of object returned - /// Reasion for object return - public void AddReturn(UUID agentID, string objectName, Vector3 location, string reason) - { - lock (m_returns) - { - if (m_returns.ContainsKey(agentID)) - { - ReturnInfo info = m_returns[agentID]; - info.count++; - m_returns[agentID] = info; - } - else - { - ReturnInfo info = new ReturnInfo(); - info.count = 1; - info.objectName = objectName; - info.location = location; - info.reason = reason; - m_returns[agentID] = info; - } - } - } - - #endregion - - #region Load Terrain - - /// - /// Store the terrain in the persistant data store - /// - public void SaveTerrain() - { - SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); - } - - public void StoreWindlightProfile(RegionLightShareData wl) - { - RegionInfo.WindlightSettings = wl; - SimulationDataService.StoreRegionWindlightSettings(wl); - m_eventManager.TriggerOnSaveNewWindlightProfile(); - } - - public void LoadWindlightProfile() - { - RegionInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(RegionInfo.RegionID); - m_eventManager.TriggerOnSaveNewWindlightProfile(); - } - - /// - /// Loads the World heightmap - /// - public override void LoadWorldMap() - { - try - { - TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); - if (map == null) - { - // This should be in the Terrain module, but it isn't because - // the heightmap is needed _way_ before the modules are initialized... - IConfig terrainConfig = m_config.Configs["Terrain"]; - String m_InitialTerrain = "pinhead-island"; - if (terrainConfig != null) - m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); - - m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); - Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); - - SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); - } - else - { - Heightmap = new TerrainChannel(map); - } - } - catch (IOException e) - { - m_log.WarnFormat( - "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}", - e.Message, e.StackTrace); + m_log.InfoFormat("[SCENE]: Loaded {0} objects from the datastore", PrimsFromDB.Count); - // Non standard region size. If there's an old terrain in the database, it might read past the buffer -#pragma warning disable 0162 - if ((int)Constants.RegionSize != 256) + foreach (SceneObjectGroup group in PrimsFromDB) { - Heightmap = new TerrainChannel(); + AddRestoredSceneObject(group, true, true); + EventManager.TriggerOnSceneObjectLoaded(group); + SceneObjectPart rootPart = group.GetPart(group.UUID); + rootPart.Flags &= ~PrimFlags.Scripted; + rootPart.TrimPermissions(); - SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); + // Don't do this here - it will get done later on when sculpt data is loaded. + // group.CheckSculptAndLoad(); } - } - catch (Exception e) - { - m_log.WarnFormat( - "[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}", e.Message, e.StackTrace); - } - } - - /// - /// Register this region with a grid service - /// - /// Thrown if registration of the region itself fails. - public void RegisterRegionWithGrid() - { - m_sceneGridService.SetScene(this); - - //// Unfortunately this needs to be here and it can't be async. - //// The map tile image is stored in RegionSettings, but it also needs to be - //// stored in the GridService, because that's what the world map module uses - //// to send the map image UUIDs (of other regions) to the viewer... - if (m_generateMaptiles) - RegenerateMaptile(); - GridRegion region = new GridRegion(RegionInfo); - string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); - // m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>", - // m_regionName, - // RegionInfo.RegionID, - // RegionInfo.RegionLocX, RegionInfo.RegionLocY, - // RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); + LoadingPrims = false; + EventManager.TriggerPrimsLoaded(this); + } - if (error != String.Empty) - throw new Exception(error); - } + public bool SupportsRayCastFiltered() + { + if (PhysicsScene == null) + return false; + return PhysicsScene.SupportsRaycastWorldFiltered(); + } - #endregion + public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) + { + if (PhysicsScene == null) + return null; + return PhysicsScene.RaycastWorld(position, direction, length, Count, filter); + } + + /// + /// Gets a new rez location based on the raycast and the size of the object that is being rezzed. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) + { + Vector3 pos = Vector3.Zero; + if (RayEndIsIntersection == (byte)1) + { + pos = RayEnd; + return pos; + } + + if (RayTargetID != UUID.Zero) + { + SceneObjectPart target = GetSceneObjectPart(RayTargetID); + + Vector3 direction = Vector3.Normalize(RayEnd - RayStart); + Vector3 AXOrigin = RayStart; + Vector3 AXdirection = direction; + + if (target != null) + { + pos = target.AbsolutePosition; + //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); + + // TODO: Raytrace better here + + //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); + Ray NewRay = new Ray(AXOrigin, AXdirection); + + // Ray Trace against target here + EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); + + // Un-comment out the following line to Get Raytrace results printed to the console. + // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); + float ScaleOffset = 0.5f; + + // If we hit something + if (ei.HitTF) + { + Vector3 scaleComponent = ei.AAfaceNormal; + if (scaleComponent.X != 0) ScaleOffset = scale.X; + if (scaleComponent.Y != 0) ScaleOffset = scale.Y; + if (scaleComponent.Z != 0) ScaleOffset = scale.Z; + ScaleOffset = Math.Abs(ScaleOffset); + Vector3 intersectionpoint = ei.ipoint; + Vector3 normal = ei.normal; + // Set the position to the intersection point + Vector3 offset = (normal * (ScaleOffset / 2f)); + pos = (intersectionpoint + offset); + + //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f + //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method + // Un-offset the prim (it gets offset later by the consumer method) + //pos.Z -= 0.25F; + + } + + return pos; + } + else + { + // We don't have a target here, so we're going to raytrace all the objects in the scene. + + EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); + + // Un-comment the following line to print the raytrace results to the console. + //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); + + if (ei.HitTF) + { + pos = ei.ipoint; + } + else + { + // fall back to our stupid functionality + pos = RayEnd; + } + + return pos; + } + } + else + { + // fall back to our stupid functionality + pos = RayEnd; + + //increase height so its above the ground. + //should be getting the normal of the ground at the rez point and using that? + pos.Z += scale.Z / 2f; + return pos; + } + } - #region Load Land - /// - /// Loads all Parcel data from the datastore for region identified by regionID - /// - /// Unique Identifier of the Region to load parcel data for - public void loadAllLandObjectsFromStorage(UUID regionID) - { - m_log.Info("[SCENE]: Loading land objects from storage"); - List landData = SimulationDataService.LoadLandObjects(regionID); + /// + /// Create a New SceneObjectGroup/Part by raycasting + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public virtual void AddNewPrim(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape, + byte bypassRaycast, Vector3 RayStart, UUID RayTargetID, + byte RayEndIsIntersection) + { + Vector3 pos = GetNewRezLocation(RayStart, RayEnd, RayTargetID, rot, bypassRaycast, RayEndIsIntersection, true, new Vector3(0.5f, 0.5f, 0.5f), false); - if (LandChannel != null) - { - if (landData.Count == 0) + if (Permissions.CanRezObject(1, ownerID, pos)) { - EventManager.TriggerNoticeNoLandDataFromStorage(); + // rez ON the ground, not IN the ground + // pos.Z += 0.25F; The rez point should now be correct so that its not in the ground + + AddNewPrim(ownerID, groupID, pos, rot, shape); } else { - EventManager.TriggerIncomingLandDataFromStorage(landData); + IClientAPI client = null; + if (TryGetClient(ownerID, out client)) + client.SendAlertMessage("You cannot create objects here."); } - } - else - { - m_log.Error("[SCENE]: Land Channel is not defined. Cannot load from storage!"); - } - } + } - #endregion + public virtual SceneObjectGroup AddNewPrim( + UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) + { + //m_log.DebugFormat( + // "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName); - #region Primitives Methods + SceneObjectGroup sceneObject = null; - /// - /// Loads the World's objects - /// - /// - public virtual void LoadPrimsFromStorage(UUID regionID) - { - LoadingPrims = true; - m_log.Info("[SCENE]: Loading objects from datastore"); - - List PrimsFromDB = SimulationDataService.LoadObjects(regionID); + // If an entity creator has been registered for this prim type then use that + if (m_entityCreators.ContainsKey((PCode)shape.PCode)) + { + sceneObject = m_entityCreators[(PCode)shape.PCode].CreateEntity(ownerID, groupID, pos, rot, shape); + } + else + { + // Otherwise, use this default creation code; + sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); + AddNewSceneObject(sceneObject, true); + sceneObject.SetGroup(groupID, null); + } - m_log.InfoFormat("[SCENE]: Loaded {0} objects from the datastore", PrimsFromDB.Count); + if (UserManagementModule != null) + sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID); - foreach (SceneObjectGroup group in PrimsFromDB) - { - AddRestoredSceneObject(group, true, true); - EventManager.TriggerOnSceneObjectLoaded(group); - SceneObjectPart rootPart = group.GetPart(group.UUID); - rootPart.Flags &= ~PrimFlags.Scripted; - rootPart.TrimPermissions(); + sceneObject.ScheduleGroupForFullUpdate(); + + return sceneObject; + } + + /// + /// Add an object into the scene that has come from storage + /// + /// + /// + /// + /// If true, changes to the object will be reflected in its persisted data + /// If false, the persisted data will not be changed even if the object in the scene is changed + /// + /// + /// If true, we won't persist this object until it changes + /// If false, we'll persist this object immediately + /// + /// + /// If true, we send updates to the client to tell it about this object + /// If false, we leave it up to the caller to do this + /// + /// + /// true if the object was added, false if an object with the same uuid was already in the scene + /// + public bool AddRestoredSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) + { + if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) + { + EventManager.TriggerObjectAddedToScene(sceneObject); + return true; + } - // Don't do this here - it will get done later on when sculpt data is loaded. - // group.CheckSculptAndLoad(); - } + return false; - LoadingPrims = false; - EventManager.TriggerPrimsLoaded(this); - } + } + + /// + /// Add an object into the scene that has come from storage + /// + /// + /// + /// + /// If true, changes to the object will be reflected in its persisted data + /// If false, the persisted data will not be changed even if the object in the scene is changed + /// + /// + /// If true, we won't persist this object until it changes + /// If false, we'll persist this object immediately + /// + /// + /// true if the object was added, false if an object with the same uuid was already in the scene + /// + public bool AddRestoredSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) + { + return AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); + } + + /// + /// Add a newly created object to the scene. Updates are also sent to viewers. + /// + /// + /// + /// If true, the object is made persistent into the scene. + /// If false, the object will not persist over server restarts + /// + /// true if the object was added. false if not + public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) + { + return AddNewSceneObject(sceneObject, attachToBackup, true); + } + + /// + /// Add a newly created object to the scene + /// + /// + /// + /// If true, the object is made persistent into the scene. + /// If false, the object will not persist over server restarts + /// + /// + /// If true, updates for the new scene object are sent to all viewers in range. + /// If false, it is left to the caller to schedule the update + /// + /// true if the object was added. false if not + public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) + { + if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates)) + { + EventManager.TriggerObjectAddedToScene(sceneObject); + return true; + } - public bool SupportsRayCastFiltered() - { - if (PhysicsScene == null) return false; - return PhysicsScene.SupportsRaycastWorldFiltered(); - } - - public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) - { - if (PhysicsScene == null) - return null; - return PhysicsScene.RaycastWorld(position, direction, length, Count, filter); - } - - /// - /// Gets a new rez location based on the raycast and the size of the object that is being rezzed. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) - { - Vector3 pos = Vector3.Zero; - if (RayEndIsIntersection == (byte)1) - { - pos = RayEnd; - return pos; - } - - if (RayTargetID != UUID.Zero) - { - SceneObjectPart target = GetSceneObjectPart(RayTargetID); - - Vector3 direction = Vector3.Normalize(RayEnd - RayStart); - Vector3 AXOrigin = RayStart; - Vector3 AXdirection = direction; - - if (target != null) - { - pos = target.AbsolutePosition; - //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); - - // TODO: Raytrace better here - - //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); - Ray NewRay = new Ray(AXOrigin, AXdirection); - - // Ray Trace against target here - EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); - - // Un-comment out the following line to Get Raytrace results printed to the console. - // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); - float ScaleOffset = 0.5f; - - // If we hit something - if (ei.HitTF) - { - Vector3 scaleComponent = ei.AAfaceNormal; - if (scaleComponent.X != 0) ScaleOffset = scale.X; - if (scaleComponent.Y != 0) ScaleOffset = scale.Y; - if (scaleComponent.Z != 0) ScaleOffset = scale.Z; - ScaleOffset = Math.Abs(ScaleOffset); - Vector3 intersectionpoint = ei.ipoint; - Vector3 normal = ei.normal; - // Set the position to the intersection point - Vector3 offset = (normal * (ScaleOffset / 2f)); - pos = (intersectionpoint + offset); - - //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f - //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method - // Un-offset the prim (it gets offset later by the consumer method) - //pos.Z -= 0.25F; - - } - - return pos; + } + + /// + /// Add a newly created object to the scene. + /// + /// + /// This method does not send updates to the client - callers need to handle this themselves. + /// + /// + /// + /// Position of the object. If null then the position stored in the object is used. + /// Rotation of the object. If null then the rotation stored in the object is used. + /// Velocity of the object. This parameter only has an effect if the object is physical + /// + public bool AddNewSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) + { + if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel)) + { + EventManager.TriggerObjectAddedToScene(sceneObject); + return true; } - else - { - // We don't have a target here, so we're going to raytrace all the objects in the scene. - - EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); - - // Un-comment the following line to print the raytrace results to the console. - //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); - - if (ei.HitTF) - { - pos = ei.ipoint; - } - else - { - // fall back to our stupid functionality - pos = RayEnd; - } - - return pos; - } - } - else - { - // fall back to our stupid functionality - pos = RayEnd; - - //increase height so its above the ground. - //should be getting the normal of the ground at the rez point and using that? - pos.Z += scale.Z / 2f; - return pos; - } - } - - - /// - /// Create a New SceneObjectGroup/Part by raycasting - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public virtual void AddNewPrim(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape, - byte bypassRaycast, Vector3 RayStart, UUID RayTargetID, - byte RayEndIsIntersection) - { - Vector3 pos = GetNewRezLocation(RayStart, RayEnd, RayTargetID, rot, bypassRaycast, RayEndIsIntersection, true, new Vector3(0.5f, 0.5f, 0.5f), false); - - if (Permissions.CanRezObject(1, ownerID, pos)) - { - // rez ON the ground, not IN the ground - // pos.Z += 0.25F; The rez point should now be correct so that its not in the ground - - AddNewPrim(ownerID, groupID, pos, rot, shape); - } - else - { - IClientAPI client = null; - if (TryGetClient(ownerID, out client)) - client.SendAlertMessage("You cannot create objects here."); - } - } - - public virtual SceneObjectGroup AddNewPrim( - UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) - { - //m_log.DebugFormat( - // "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName); - - SceneObjectGroup sceneObject = null; - - // If an entity creator has been registered for this prim type then use that - if (m_entityCreators.ContainsKey((PCode)shape.PCode)) - { - sceneObject = m_entityCreators[(PCode)shape.PCode].CreateEntity(ownerID, groupID, pos, rot, shape); - } - else - { - // Otherwise, use this default creation code; - sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - AddNewSceneObject(sceneObject, true); - sceneObject.SetGroup(groupID, null); - } - - if (UserManagementModule != null) - sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID); - sceneObject.ScheduleGroupForFullUpdate(); - - return sceneObject; - } - - /// - /// Add an object into the scene that has come from storage - /// - /// - /// - /// - /// If true, changes to the object will be reflected in its persisted data - /// If false, the persisted data will not be changed even if the object in the scene is changed - /// - /// - /// If true, we won't persist this object until it changes - /// If false, we'll persist this object immediately - /// - /// - /// If true, we send updates to the client to tell it about this object - /// If false, we leave it up to the caller to do this - /// - /// - /// true if the object was added, false if an object with the same uuid was already in the scene - /// - public bool AddRestoredSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) - { - if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) - { - EventManager.TriggerObjectAddedToScene(sceneObject); - return true; - } - - return false; - - } - - /// - /// Add an object into the scene that has come from storage - /// - /// - /// - /// - /// If true, changes to the object will be reflected in its persisted data - /// If false, the persisted data will not be changed even if the object in the scene is changed - /// - /// - /// If true, we won't persist this object until it changes - /// If false, we'll persist this object immediately - /// - /// - /// true if the object was added, false if an object with the same uuid was already in the scene - /// - public bool AddRestoredSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) - { - return AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); - } - - /// - /// Add a newly created object to the scene. Updates are also sent to viewers. - /// - /// - /// - /// If true, the object is made persistent into the scene. - /// If false, the object will not persist over server restarts - /// - /// true if the object was added. false if not - public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) - { - return AddNewSceneObject(sceneObject, attachToBackup, true); - } - - /// - /// Add a newly created object to the scene - /// - /// - /// - /// If true, the object is made persistent into the scene. - /// If false, the object will not persist over server restarts - /// - /// - /// If true, updates for the new scene object are sent to all viewers in range. - /// If false, it is left to the caller to schedule the update - /// - /// true if the object was added. false if not - public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) - { - if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates)) - { - EventManager.TriggerObjectAddedToScene(sceneObject); - return true; - } - - return false; - } - - /// - /// Add a newly created object to the scene. - /// - /// - /// This method does not send updates to the client - callers need to handle this themselves. - /// - /// - /// - /// Position of the object. If null then the position stored in the object is used. - /// Rotation of the object. If null then the rotation stored in the object is used. - /// Velocity of the object. This parameter only has an effect if the object is physical - /// - public bool AddNewSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) - { - if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel)) - { - EventManager.TriggerObjectAddedToScene(sceneObject); - return true; - } - - return false; - } - - /// - /// Delete every object from the scene. This does not include attachments worn by avatars. - /// - public void DeleteAllSceneObjects() - { - lock (Entities) - { - EntityBase[] entities = Entities.GetEntities(); - foreach (EntityBase e in entities) - { - if (e is SceneObjectGroup) - { - SceneObjectGroup sog = (SceneObjectGroup)e; - if (!sog.IsAttachment) - DeleteSceneObject((SceneObjectGroup)e, false); - } - } - } - } - - /// - /// Synchronously delete the given object from the scene. - /// - /// - /// Scripts are also removed. - /// - /// Object Id - /// Suppress broadcasting changes to other clients. - public void DeleteSceneObject(SceneObjectGroup group, bool silent) - { - DeleteSceneObject(group, silent, true); - } - - /// - /// Synchronously delete the given object from the scene. - /// - /// Object Id - /// Suppress broadcasting changes to other clients. - /// If true, then scripts are removed. If false, then they are only stopped. - public void DeleteSceneObject(SceneObjectGroup group, bool silent, bool removeScripts) - { - // m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); - - if (removeScripts) + return false; + } + + /// + /// Delete every object from the scene. This does not include attachments worn by avatars. + /// + public void DeleteAllSceneObjects() + { + lock (Entities) + { + EntityBase[] entities = Entities.GetEntities(); + foreach (EntityBase e in entities) + { + if (e is SceneObjectGroup) + { + SceneObjectGroup sog = (SceneObjectGroup)e; + if (!sog.IsAttachment) + DeleteSceneObject((SceneObjectGroup)e, false); + } + } + } + } + + /// + /// Synchronously delete the given object from the scene. + /// + /// + /// Scripts are also removed. + /// + /// Object Id + /// Suppress broadcasting changes to other clients. + public void DeleteSceneObject(SceneObjectGroup group, bool silent) + { + DeleteSceneObject(group, silent, true); + } + + /// + /// Synchronously delete the given object from the scene. + /// + /// Object Id + /// Suppress broadcasting changes to other clients. + /// If true, then scripts are removed. If false, then they are only stopped. + public void DeleteSceneObject(SceneObjectGroup group, bool silent, bool removeScripts) + { + // m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); + + if (removeScripts) group.RemoveScriptInstances(true); - else + else group.StopScriptInstances(); - SceneObjectPart[] partList = group.Parts; + SceneObjectPart[] partList = group.Parts; - foreach (SceneObjectPart part in partList) - { - if (part.KeyframeMotion != null) + foreach (SceneObjectPart part in partList) { - part.KeyframeMotion.Delete(); - part.KeyframeMotion = null; - } + if (part.KeyframeMotion != null) + { + part.KeyframeMotion.Delete(); + part.KeyframeMotion = null; + } - if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) - { - PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? + if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) + { + PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? + } + else if (part.PhysActor != null) + { + part.RemoveFromPhysics(); + } } - else if (part.PhysActor != null) + + if (UnlinkSceneObject(group, false)) { - part.RemoveFromPhysics(); + EventManager.TriggerObjectBeingRemovedFromScene(group); + EventManager.TriggerParcelPrimCountTainted(); } - } - - if (UnlinkSceneObject(group, false)) - { - EventManager.TriggerObjectBeingRemovedFromScene(group); - EventManager.TriggerParcelPrimCountTainted(); - } - group.DeleteGroupFromScene(silent); + group.DeleteGroupFromScene(silent); - // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); - } + // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); + } - /// - /// Unlink the given object from the scene. Unlike delete, this just removes the record of the object - the - /// object itself is not destroyed. - /// - /// The scene object. - /// If true, only deletes from scene, but keeps the object in the database. - /// true if the object was in the scene, false if it was not - public bool UnlinkSceneObject(SceneObjectGroup so, bool softDelete) - { - if (m_sceneGraph.DeleteSceneObject(so.UUID, softDelete)) - { - if (!softDelete) + /// + /// Unlink the given object from the scene. Unlike delete, this just removes the record of the object - the + /// object itself is not destroyed. + /// + /// The scene object. + /// If true, only deletes from scene, but keeps the object in the database. + /// true if the object was in the scene, false if it was not + public bool UnlinkSceneObject(SceneObjectGroup so, bool softDelete) + { + if (m_sceneGraph.DeleteSceneObject(so.UUID, softDelete)) { - // If the group contains prims whose SceneGroupID is incorrect then force a - // database update, because RemoveObject() works by searching on the SceneGroupID. - // This is an expensive thing to do so only do it if absolutely necessary. - if (so.GroupContainsForeignPrims) - ForceSceneObjectBackup(so); + if (!softDelete) + { + // If the group contains prims whose SceneGroupID is incorrect then force a + // database update, because RemoveObject() works by searching on the SceneGroupID. + // This is an expensive thing to do so only do it if absolutely necessary. + if (so.GroupContainsForeignPrims) + ForceSceneObjectBackup(so); - so.DetachFromBackup(); - SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID); - } + so.DetachFromBackup(); + SimulationDataService.RemoveObject(so.UUID, RegionInfo.RegionID); + } - // We need to keep track of this state in case this group is still queued for further backup. - so.IsDeleted = true; + // We need to keep track of this state in case this group is still queued for further backup. + so.IsDeleted = true; - return true; - } - - return false; - } - - /// - /// Move the given scene object into a new region depending on which region its absolute position has moved - /// into. - /// - /// - /// the attempted out of region position of the scene object - /// the scene object that we're crossing - public void CrossPrimGroupIntoNewRegion(Vector3 attemptedPosition, SceneObjectGroup grp, bool silent) - { - if (grp == null) + return true; + } + + return false; + } + + /// + /// Move the given scene object into a new region depending on which region its absolute position has moved + /// into. + /// + /// + /// the attempted out of region position of the scene object + /// the scene object that we're crossing + public void CrossPrimGroupIntoNewRegion(Vector3 attemptedPosition, SceneObjectGroup grp, bool silent) + { + if (grp == null) return; - if (grp.IsDeleted) + if (grp.IsDeleted) return; - if (grp.RootPart.DIE_AT_EDGE) - { - // We remove the object here - try + if (grp.RootPart.DIE_AT_EDGE) + { + // We remove the object here + try + { + DeleteSceneObject(grp, false); + } + catch (Exception) + { + m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border."); + } + return; + } + + if (grp.RootPart.RETURN_AT_EDGE) + { + // We remove the object here + try + { + List objects = new List(); + objects.Add(grp); + SceneObjectGroup[] objectsArray = objects.ToArray(); + returnObjects(objectsArray, UUID.Zero); + } + catch (Exception) + { + m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border."); + } + return; + } + + if (EntityTransferModule != null) + EntityTransferModule.Cross(grp, attemptedPosition, silent); + } + + // Simple test to see if a position is in the current region. + // This test is mostly used to see if a region crossing is necessary. + // Assuming the position is relative to the region so anything outside its bounds. + // Return 'true' if position inside region. + public bool PositionIsInCurrentRegion(Vector3 pos) + { + bool ret = false; + int xx = (int)Math.Floor(pos.X); + int yy = (int)Math.Floor(pos.Y); + if (xx < 0 || yy < 0) + return false; + + IRegionCombinerModule regionCombinerModule = RequestModuleInterface(); + if (regionCombinerModule == null) { - DeleteSceneObject(grp, false); + // Regular region. Just check for region size + if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY) + ret = true; } - catch (Exception) + else { - m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border."); + // We're in a mega-region so see if we are still in that larger region + ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy); } - return; - } - if (grp.RootPart.RETURN_AT_EDGE) - { - // We remove the object here + return ret; + + } + + /// + /// Called when objects or attachments cross the border, or teleport, between regions. + /// + /// + /// + public bool IncomingCreateObject(Vector3 newPosition, ISceneObject sog) + { + //m_log.DebugFormat(" >>> IncomingCreateObject(sog) <<< {0} deleted? {1} isAttach? {2}", ((SceneObjectGroup)sog).AbsolutePosition, + // ((SceneObjectGroup)sog).IsDeleted, ((SceneObjectGroup)sog).RootPart.IsAttachment); + + SceneObjectGroup newObject; try { - List objects = new List(); - objects.Add(grp); - SceneObjectGroup[] objectsArray = objects.ToArray(); - returnObjects(objectsArray, UUID.Zero); + newObject = (SceneObjectGroup)sog; } - catch (Exception) + catch (Exception e) { - m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border."); + m_log.WarnFormat("[INTERREGION]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace); + return false; } - return; - } - if (EntityTransferModule != null) - EntityTransferModule.Cross(grp, attemptedPosition, silent); - } - - // Simple test to see if a position is in the current region. - // This test is mostly used to see if a region crossing is necessary. - // Assuming the position is relative to the region so anything outside its bounds. - // Return 'true' if position inside region. - public bool PositionIsInCurrentRegion(Vector3 pos) - { - bool ret = false; - int xx = (int)Math.Floor(pos.X); - int yy = (int)Math.Floor(pos.Y); - if (xx < 0 || yy < 0) + if (!EntityTransferModule.HandleIncomingSceneObject(newObject, newPosition)) return false; - IRegionCombinerModule regionCombinerModule = RequestModuleInterface(); - if (regionCombinerModule == null) - { - // Regular region. Just check for region size - if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY) - ret = true; - } - else - { - // We're in a mega-region so see if we are still in that larger region - ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy); - } - - return ret; - - } - - /// - /// Called when objects or attachments cross the border, or teleport, between regions. - /// - /// - /// - public bool IncomingCreateObject(Vector3 newPosition, ISceneObject sog) - { - //m_log.DebugFormat(" >>> IncomingCreateObject(sog) <<< {0} deleted? {1} isAttach? {2}", ((SceneObjectGroup)sog).AbsolutePosition, - // ((SceneObjectGroup)sog).IsDeleted, ((SceneObjectGroup)sog).RootPart.IsAttachment); - - SceneObjectGroup newObject; - try - { - newObject = (SceneObjectGroup)sog; - } - catch (Exception e) - { - m_log.WarnFormat("[INTERREGION]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace); - return false; - } + // Do this as late as possible so that listeners have full access to the incoming object + EventManager.TriggerOnIncomingSceneObject(newObject); - if (!EntityTransferModule.HandleIncomingSceneObject(newObject, newPosition)) - return false; - - // Do this as late as possible so that listeners have full access to the incoming object - EventManager.TriggerOnIncomingSceneObject(newObject); - - return true; - } - - /// - /// Adds a Scene Object group to the Scene. - /// Verifies that the creator of the object is not banned from the simulator. - /// Checks if the item is an Attachment - /// - /// - /// True if the SceneObjectGroup was added, False if it was not - public bool AddSceneObject(SceneObjectGroup sceneObject) - { - // Force allocation of new LocalId - // - SceneObjectPart[] parts = sceneObject.Parts; - for (int i = 0; i < parts.Length; i++) + return true; + } + + /// + /// Adds a Scene Object group to the Scene. + /// Verifies that the creator of the object is not banned from the simulator. + /// Checks if the item is an Attachment + /// + /// + /// True if the SceneObjectGroup was added, False if it was not + public bool AddSceneObject(SceneObjectGroup sceneObject) + { + // Force allocation of new LocalId + // + SceneObjectPart[] parts = sceneObject.Parts; + for (int i = 0; i < parts.Length; i++) parts[i].LocalId = 0; - if (sceneObject.IsAttachmentCheckFull()) // Attachment - { - sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); - sceneObject.RootPart.AddFlag(PrimFlags.Phantom); + if (sceneObject.IsAttachmentCheckFull()) // Attachment + { + sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); + sceneObject.RootPart.AddFlag(PrimFlags.Phantom); - // Don't sent a full update here because this will cause full updates to be sent twice for - // attachments on region crossings, resulting in viewer glitches. - AddRestoredSceneObject(sceneObject, false, false, false); + // Don't sent a full update here because this will cause full updates to be sent twice for + // attachments on region crossings, resulting in viewer glitches. + AddRestoredSceneObject(sceneObject, false, false, false); - // Handle attachment special case - SceneObjectPart RootPrim = sceneObject.RootPart; + // Handle attachment special case + SceneObjectPart RootPrim = sceneObject.RootPart; - // Fix up attachment Parent Local ID - ScenePresence sp = GetScenePresence(sceneObject.OwnerID); + // Fix up attachment Parent Local ID + ScenePresence sp = GetScenePresence(sceneObject.OwnerID); - if (sp != null) - { - SceneObjectGroup grp = sceneObject; + if (sp != null) + { + SceneObjectGroup grp = sceneObject; - // m_log.DebugFormat( - // "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID); - // m_log.DebugFormat( - // "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); + // m_log.DebugFormat( + // "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID); + // m_log.DebugFormat( + // "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); - RootPrim.RemFlag(PrimFlags.TemporaryOnRez); + RootPrim.RemFlag(PrimFlags.TemporaryOnRez); - // We must currently not resume scripts at this stage since AttachmentsModule does not have the - // information that this is due to a teleport/border cross rather than an ordinary attachment. - // We currently do this in Scene.MakeRootAgent() instead. - if (AttachmentsModule != null) - AttachmentsModule.AttachObject(sp, grp, 0, false, false, true); + // We must currently not resume scripts at this stage since AttachmentsModule does not have the + // information that this is due to a teleport/border cross rather than an ordinary attachment. + // We currently do this in Scene.MakeRootAgent() instead. + if (AttachmentsModule != null) + AttachmentsModule.AttachObject(sp, grp, 0, false, false, true); + } + else + { + RootPrim.RemFlag(PrimFlags.TemporaryOnRez); + RootPrim.AddFlag(PrimFlags.TemporaryOnRez); + } } else { - RootPrim.RemFlag(PrimFlags.TemporaryOnRez); - RootPrim.AddFlag(PrimFlags.TemporaryOnRez); - } - } - else - { - AddRestoredSceneObject(sceneObject, true, false); - } - - return true; - } - - #endregion - - #region Add/Remove Avatar Methods - - public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) - { - ScenePresence sp; - bool vialogin; - bool reallyNew = true; - - // Update the number of users attempting to login - StatsReporter.UpdateUsersLoggingIn(true); - - // Validation occurs in LLUDPServer - // - // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with - // each other. In practice, this does not currently occur in the code. - AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); - - // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection - // and a simultaneous one that removes it (as can happen if the client is closed at a particular point - // whilst connecting). - // - // It would be easier to lock across all NewUserConnection(), AddNewAgent() and - // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service - // response in some module listening to AddNewAgent()) from holding up unrelated agent calls. - // - // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all - // AddNewClient() operations (though not other ops). - // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. - lock (aCircuit) - { - vialogin - = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 - || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; + AddRestoredSceneObject(sceneObject, true, false); + } - // CheckHeartbeat(); + return true; + } - sp = GetScenePresence(client.AgentId); + #endregion - // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this - // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause - // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already - // connected. - if (sp == null) - { - m_log.DebugFormat( - "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", - client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); + #region Add/Remove Avatar Methods - sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); + public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) + { + ScenePresence sp; + bool vialogin; + bool reallyNew = true; - // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the - // client is for a root or child agent. - // We must also set this before adding the client to the client manager so that an exception later on - // does not leave a client manager entry without the scene agent set, which will cause other code - // to fail since any entry in the client manager should have a ScenePresence - // - // XXX: This may be better set for a new client before that client is added to the client manager. - // But need to know what happens in the case where a ScenePresence is already present (and if this - // actually occurs). - client.SceneAgent = sp; + // Update the number of users attempting to login + StatsReporter.UpdateUsersLoggingIn(true); - m_clientManager.Add(client); - SubscribeToClientEvents(client); - m_eventManager.TriggerOnNewPresence(sp); + // Validation occurs in LLUDPServer + // + // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with + // each other. In practice, this does not currently occur in the code. + AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); - sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; - } - else + // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection + // and a simultaneous one that removes it (as can happen if the client is closed at a particular point + // whilst connecting). + // + // It would be easier to lock across all NewUserConnection(), AddNewAgent() and + // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service + // response in some module listening to AddNewAgent()) from holding up unrelated agent calls. + // + // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all + // AddNewClient() operations (though not other ops). + // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. + lock (aCircuit) { - // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the - // client is for a root or child agent. - // XXX: This may be better set for a new client before that client is added to the client manager. - // But need to know what happens in the case where a ScenePresence is already present (and if this - // actually occurs). - client.SceneAgent = sp; - - m_log.WarnFormat( - "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", - sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); + vialogin + = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 + || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; + + // CheckHeartbeat(); + + sp = GetScenePresence(client.AgentId); + + // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this + // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause + // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already + // connected. + if (sp == null) + { + m_log.DebugFormat( + "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", + client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); + + sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); + + // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the + // client is for a root or child agent. + // We must also set this before adding the client to the client manager so that an exception later on + // does not leave a client manager entry without the scene agent set, which will cause other code + // to fail since any entry in the client manager should have a ScenePresence + // + // XXX: This may be better set for a new client before that client is added to the client manager. + // But need to know what happens in the case where a ScenePresence is already present (and if this + // actually occurs). + client.SceneAgent = sp; + + m_clientManager.Add(client); + SubscribeToClientEvents(client); + m_eventManager.TriggerOnNewPresence(sp); + + sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; + } + else + { + // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the + // client is for a root or child agent. + // XXX: This may be better set for a new client before that client is added to the client manager. + // But need to know what happens in the case where a ScenePresence is already present (and if this + // actually occurs). + client.SceneAgent = sp; + + m_log.WarnFormat( + "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", + sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); + + reallyNew = false; + } + + // This is currently also being done earlier in NewUserConnection for real users to see if this + // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other + // places. However, we still need to do it here for NPCs. + CacheUserName(sp, aCircuit); + + if (reallyNew) + EventManager.TriggerOnNewClient(client); + + if (vialogin) + EventManager.TriggerOnClientLogin(client); + } + + // User has logged into the scene so update the list of users logging + // in + StatsReporter.UpdateUsersLoggingIn(false); + + m_LastLogin = Util.EnvironmentTickCount(); + + return sp; + } + + /// + /// Returns the Home URI of the agent, or null if unknown. + /// + public string GetAgentHomeURI(UUID agentID) + { + AgentCircuitData circuit = AuthenticateHandler.GetAgentCircuitData(agentID); + if (circuit != null && circuit.ServiceURLs != null && circuit.ServiceURLs.ContainsKey("HomeURI")) + return circuit.ServiceURLs["HomeURI"].ToString(); + else + return null; + } + + /// + /// Cache the user name for later use. + /// + /// + /// + private void CacheUserName(ScenePresence sp, AgentCircuitData aCircuit) + { + if (UserManagementModule != null) + { + string first = aCircuit.firstname, last = aCircuit.lastname; + + if (sp != null && sp.PresenceType == PresenceType.Npc) + { + UserManagementModule.AddUser(aCircuit.AgentID, first, last); + } + else + { + string homeURL = string.Empty; + + if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) + homeURL = aCircuit.ServiceURLs["HomeURI"].ToString(); + + if (aCircuit.lastname.StartsWith("@")) + { + string[] parts = aCircuit.firstname.Split('.'); + if (parts.Length >= 2) + { + first = parts[0]; + last = parts[1]; + } + } + + UserManagementModule.AddUser(aCircuit.AgentID, first, last, homeURL); + } + } + } + + private bool VerifyClient(AgentCircuitData aCircuit, System.Net.IPEndPoint ep, out bool vialogin) + { + vialogin = false; + + // Do the verification here + if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) + { + m_log.DebugFormat("[SCENE]: Incoming client {0} {1} in region {2} via HG login", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + vialogin = true; + IUserAgentVerificationModule userVerification = RequestModuleInterface(); + if (userVerification != null && ep != null) + { + if (!userVerification.VerifyClient(aCircuit, ep.Address.ToString())) + { + // uh-oh, this is fishy + m_log.DebugFormat("[SCENE]: User Client Verification for {0} {1} in {2} returned false", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + return false; + } + else + m_log.DebugFormat("[SCENE]: User Client Verification for {0} {1} in {2} returned true", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); - reallyNew = false; + } } - // This is currently also being done earlier in NewUserConnection for real users to see if this - // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other - // places. However, we still need to do it here for NPCs. - CacheUserName(sp, aCircuit); - - if (reallyNew) - EventManager.TriggerOnNewClient(client); - - if (vialogin) - EventManager.TriggerOnClientLogin(client); - } - - // User has logged into the scene so update the list of users logging - // in - StatsReporter.UpdateUsersLoggingIn(false); - - m_LastLogin = Util.EnvironmentTickCount(); - - return sp; - } + else if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0) + { + m_log.DebugFormat("[SCENE]: Incoming client {0} {1} in region {2} via regular login. Client IP verification not performed.", + aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + vialogin = true; + } - /// - /// Returns the Home URI of the agent, or null if unknown. - /// - public string GetAgentHomeURI(UUID agentID) - { - AgentCircuitData circuit = AuthenticateHandler.GetAgentCircuitData(agentID); - if (circuit != null && circuit.ServiceURLs != null && circuit.ServiceURLs.ContainsKey("HomeURI")) - return circuit.ServiceURLs["HomeURI"].ToString(); - else - return null; - } + return true; + } + + // Called by Caps, on the first HTTP contact from the client + public override bool CheckClient(UUID agentID, System.Net.IPEndPoint ep) + { + AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(agentID); + if (aCircuit != null) + { + bool vialogin = false; + if (!VerifyClient(aCircuit, ep, out vialogin)) + { + // if it doesn't pass, we remove the agentcircuitdata altogether + // and the scene presence and the client, if they exist + try + { + // We need to wait for the client to make UDP contact first. + // It's the UDP contact that creates the scene presence + ScenePresence sp = WaitGetScenePresence(agentID); + if (sp != null) + { + PresenceService.LogoutAgent(sp.ControllingClient.SessionId); + + CloseAgent(sp.UUID, false); + } + else + { + m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID); + } + // BANG! SLASH! + m_authenticateHandler.RemoveCircuit(agentID); - /// - /// Cache the user name for later use. - /// - /// - /// - private void CacheUserName(ScenePresence sp, AgentCircuitData aCircuit) - { - if (UserManagementModule != null) - { - string first = aCircuit.firstname, last = aCircuit.lastname; + return false; + } + catch (Exception e) + { + m_log.DebugFormat("[SCENE]: Exception while closing aborted client: {0}", e.StackTrace); + } + } + else + return true; + } - if (sp != null && sp.PresenceType == PresenceType.Npc) + return false; + } + + /// + /// Register for events from the client + /// + /// The IClientAPI of the connected client + public virtual void SubscribeToClientEvents(IClientAPI client) + { + SubscribeToClientTerrainEvents(client); + SubscribeToClientPrimEvents(client); + SubscribeToClientPrimRezEvents(client); + SubscribeToClientInventoryEvents(client); + SubscribeToClientTeleportEvents(client); + SubscribeToClientScriptEvents(client); + SubscribeToClientParcelEvents(client); + SubscribeToClientGridEvents(client); + SubscribeToClientNetworkEvents(client); + } + + public virtual void SubscribeToClientTerrainEvents(IClientAPI client) + { + client.OnRegionHandShakeReply += SendLayerData; + } + + public virtual void SubscribeToClientPrimEvents(IClientAPI client) + { + client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; + client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; + + client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; + client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; + 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 += DeRezObjects; + + client.OnObjectName += m_sceneGraph.PrimName; + client.OnObjectClickAction += m_sceneGraph.PrimClickAction; + client.OnObjectMaterial += m_sceneGraph.PrimMaterial; + client.OnLinkObjects += LinkObjects; + client.OnDelinkObjects += DelinkObjects; + client.OnObjectDuplicate += DuplicateObject; + client.OnObjectDuplicateOnRay += doObjectDuplicateOnRay; + client.OnUpdatePrimFlags += m_sceneGraph.UpdatePrimFlags; + client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily; + client.OnObjectPermissions += HandleObjectPermissionsUpdate; + client.OnGrabObject += ProcessObjectGrab; + client.OnGrabUpdate += ProcessObjectGrabUpdate; + client.OnDeGrabObject += ProcessObjectDeGrab; + client.OnUndo += m_sceneGraph.HandleUndo; + client.OnRedo += m_sceneGraph.HandleRedo; + client.OnObjectDescription += m_sceneGraph.PrimDescription; + client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable; + client.OnObjectOwner += ObjectOwner; + client.OnObjectGroupRequest += HandleObjectGroupUpdate; + } + + public virtual void SubscribeToClientPrimRezEvents(IClientAPI client) + { + client.OnAddPrim += AddNewPrim; + client.OnRezObject += RezObject; + } + + public virtual void SubscribeToClientInventoryEvents(IClientAPI client) + { + client.OnLinkInventoryItem += HandleLinkInventoryItem; + client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; + client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; + client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!! + client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents; + client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!! + client.OnFetchInventory += m_asyncInventorySender.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 SubscribeToClientTeleportEvents(IClientAPI client) + { + client.OnTeleportLocationRequest += RequestTeleportLocation; + } + + public virtual void SubscribeToClientScriptEvents(IClientAPI client) + { + client.OnScriptReset += ProcessScriptReset; + client.OnGetScriptRunning += GetScriptRunning; + client.OnSetScriptRunning += SetScriptRunning; + } + + public virtual void SubscribeToClientParcelEvents(IClientAPI client) + { + client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel; + client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime; + client.OnParcelBuy += ProcessParcelBuy; + } + + public virtual void SubscribeToClientGridEvents(IClientAPI client) + { + //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; + client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; + } + + public virtual void SubscribeToClientNetworkEvents(IClientAPI client) + { + client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; + client.OnViewerEffect += ProcessViewerEffect; + } + + /// + /// Unsubscribe the client from events. + /// + /// FIXME: Not called anywhere! + /// The IClientAPI of the client + public virtual void UnSubscribeToClientEvents(IClientAPI client) + { + UnSubscribeToClientTerrainEvents(client); + UnSubscribeToClientPrimEvents(client); + UnSubscribeToClientPrimRezEvents(client); + UnSubscribeToClientInventoryEvents(client); + UnSubscribeToClientTeleportEvents(client); + UnSubscribeToClientScriptEvents(client); + UnSubscribeToClientParcelEvents(client); + UnSubscribeToClientGridEvents(client); + UnSubscribeToClientNetworkEvents(client); + } + + public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) + { + client.OnRegionHandShakeReply -= SendLayerData; + } + + public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) + { + client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; + client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; + + client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; + client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; + 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 -= DeRezObjects; + client.OnObjectName -= m_sceneGraph.PrimName; + client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; + client.OnObjectMaterial -= m_sceneGraph.PrimMaterial; + client.OnLinkObjects -= LinkObjects; + client.OnDelinkObjects -= DelinkObjects; + client.OnObjectDuplicate -= 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.OnRedo -= m_sceneGraph.HandleRedo; + client.OnObjectDescription -= m_sceneGraph.PrimDescription; + 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.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; + client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; + client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! + client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents; + client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!! + client.OnFetchInventory -= m_asyncInventorySender.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 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.OnParcelReturnObjectsRequest -= LandChannel.ReturnObjectsInParcel; + client.OnParcelSetOtherCleanTime -= LandChannel.SetParcelOtherCleanTime; + client.OnParcelBuy -= ProcessParcelBuy; + } + + public virtual void UnSubscribeToClientGridEvents(IClientAPI client) + { + //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; + client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; + } + + public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) + { + client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats; + client.OnViewerEffect -= ProcessViewerEffect; + } + + /// + /// Teleport an avatar to their home region + /// + /// The avatar's Unique ID + /// The IClientAPI for the client + public virtual bool TeleportClientHome(UUID agentId, IClientAPI client) + { + if (EntityTransferModule != null) { - UserManagementModule.AddUser(aCircuit.AgentID, first, last); + return EntityTransferModule.TeleportHome(agentId, client); } else { - string homeURL = string.Empty; - - if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) - homeURL = aCircuit.ServiceURLs["HomeURI"].ToString(); - - if (aCircuit.lastname.StartsWith("@")) - { - string[] parts = aCircuit.firstname.Split('.'); - if (parts.Length >= 2) - { - first = parts[0]; - last = parts[1]; - } - } - - UserManagementModule.AddUser(aCircuit.AgentID, first, last, homeURL); - } - } - } - - private bool VerifyClient(AgentCircuitData aCircuit, System.Net.IPEndPoint ep, out bool vialogin) - { - vialogin = false; - - // Do the verification here - if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) - { - m_log.DebugFormat("[SCENE]: Incoming client {0} {1} in region {2} via HG login", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); - vialogin = true; - IUserAgentVerificationModule userVerification = RequestModuleInterface(); - if (userVerification != null && ep != null) - { - if (!userVerification.VerifyClient(aCircuit, ep.Address.ToString())) - { - // uh-oh, this is fishy - m_log.DebugFormat("[SCENE]: User Client Verification for {0} {1} in {2} returned false", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); - return false; - } - else - m_log.DebugFormat("[SCENE]: User Client Verification for {0} {1} in {2} returned true", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); - - } - } - - else if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0) - { - m_log.DebugFormat("[SCENE]: Incoming client {0} {1} in region {2} via regular login. Client IP verification not performed.", - aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); - vialogin = true; - } - - return true; - } - - // Called by Caps, on the first HTTP contact from the client - public override bool CheckClient(UUID agentID, System.Net.IPEndPoint ep) - { - AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(agentID); - if (aCircuit != null) - { - bool vialogin = false; - if (!VerifyClient(aCircuit, ep, out vialogin)) - { - // if it doesn't pass, we remove the agentcircuitdata altogether - // and the scene presence and the client, if they exist - try - { - // We need to wait for the client to make UDP contact first. - // It's the UDP contact that creates the scene presence - ScenePresence sp = WaitGetScenePresence(agentID); - if (sp != null) - { - PresenceService.LogoutAgent(sp.ControllingClient.SessionId); - - CloseAgent(sp.UUID, false); - } - else - { - m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID); - } - // BANG! SLASH! - m_authenticateHandler.RemoveCircuit(agentID); - - return false; - } - catch (Exception e) - { - m_log.DebugFormat("[SCENE]: Exception while closing aborted client: {0}", e.StackTrace); - } + m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); + client.SendTeleportFailed("Unable to perform teleports on this simulator."); } - else - return true; - } - - return false; - } - - /// - /// Register for events from the client - /// - /// The IClientAPI of the connected client - public virtual void SubscribeToClientEvents(IClientAPI client) - { - SubscribeToClientTerrainEvents(client); - SubscribeToClientPrimEvents(client); - SubscribeToClientPrimRezEvents(client); - SubscribeToClientInventoryEvents(client); - SubscribeToClientTeleportEvents(client); - SubscribeToClientScriptEvents(client); - SubscribeToClientParcelEvents(client); - SubscribeToClientGridEvents(client); - SubscribeToClientNetworkEvents(client); - } - - public virtual void SubscribeToClientTerrainEvents(IClientAPI client) - { - client.OnRegionHandShakeReply += SendLayerData; - } - - public virtual void SubscribeToClientPrimEvents(IClientAPI client) - { - client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; - client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; - - client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; - client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; - 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 += DeRezObjects; - - client.OnObjectName += m_sceneGraph.PrimName; - client.OnObjectClickAction += m_sceneGraph.PrimClickAction; - client.OnObjectMaterial += m_sceneGraph.PrimMaterial; - client.OnLinkObjects += LinkObjects; - client.OnDelinkObjects += DelinkObjects; - client.OnObjectDuplicate += DuplicateObject; - client.OnObjectDuplicateOnRay += doObjectDuplicateOnRay; - client.OnUpdatePrimFlags += m_sceneGraph.UpdatePrimFlags; - client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily; - client.OnObjectPermissions += HandleObjectPermissionsUpdate; - client.OnGrabObject += ProcessObjectGrab; - client.OnGrabUpdate += ProcessObjectGrabUpdate; - client.OnDeGrabObject += ProcessObjectDeGrab; - client.OnUndo += m_sceneGraph.HandleUndo; - client.OnRedo += m_sceneGraph.HandleRedo; - client.OnObjectDescription += m_sceneGraph.PrimDescription; - client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable; - client.OnObjectOwner += ObjectOwner; - client.OnObjectGroupRequest += HandleObjectGroupUpdate; - } - - public virtual void SubscribeToClientPrimRezEvents(IClientAPI client) - { - client.OnAddPrim += AddNewPrim; - client.OnRezObject += RezObject; - } - - public virtual void SubscribeToClientInventoryEvents(IClientAPI client) - { - client.OnLinkInventoryItem += HandleLinkInventoryItem; - client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; - client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; - client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!! - client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents; - client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!! - client.OnFetchInventory += m_asyncInventorySender.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 SubscribeToClientTeleportEvents(IClientAPI client) - { - client.OnTeleportLocationRequest += RequestTeleportLocation; - } - - public virtual void SubscribeToClientScriptEvents(IClientAPI client) - { - client.OnScriptReset += ProcessScriptReset; - client.OnGetScriptRunning += GetScriptRunning; - client.OnSetScriptRunning += SetScriptRunning; - } - - public virtual void SubscribeToClientParcelEvents(IClientAPI client) - { - client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel; - client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime; - client.OnParcelBuy += ProcessParcelBuy; - } - - public virtual void SubscribeToClientGridEvents(IClientAPI client) - { - //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; - client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; - } - - public virtual void SubscribeToClientNetworkEvents(IClientAPI client) - { - client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; - client.OnViewerEffect += ProcessViewerEffect; - } - - /// - /// Unsubscribe the client from events. - /// - /// FIXME: Not called anywhere! - /// The IClientAPI of the client - public virtual void UnSubscribeToClientEvents(IClientAPI client) - { - UnSubscribeToClientTerrainEvents(client); - UnSubscribeToClientPrimEvents(client); - UnSubscribeToClientPrimRezEvents(client); - UnSubscribeToClientInventoryEvents(client); - UnSubscribeToClientTeleportEvents(client); - UnSubscribeToClientScriptEvents(client); - UnSubscribeToClientParcelEvents(client); - UnSubscribeToClientGridEvents(client); - UnSubscribeToClientNetworkEvents(client); - } - - public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) - { - client.OnRegionHandShakeReply -= SendLayerData; - } - - public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) - { - client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; - client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; - - client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; - client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; - 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 -= DeRezObjects; - client.OnObjectName -= m_sceneGraph.PrimName; - client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; - client.OnObjectMaterial -= m_sceneGraph.PrimMaterial; - client.OnLinkObjects -= LinkObjects; - client.OnDelinkObjects -= DelinkObjects; - client.OnObjectDuplicate -= 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.OnRedo -= m_sceneGraph.HandleRedo; - client.OnObjectDescription -= m_sceneGraph.PrimDescription; - 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.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; - client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; - client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! - client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents; - client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!! - client.OnFetchInventory -= m_asyncInventorySender.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 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.OnParcelReturnObjectsRequest -= LandChannel.ReturnObjectsInParcel; - client.OnParcelSetOtherCleanTime -= LandChannel.SetParcelOtherCleanTime; - client.OnParcelBuy -= ProcessParcelBuy; - } - - public virtual void UnSubscribeToClientGridEvents(IClientAPI client) - { - //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; - client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; - } - - public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) - { - client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats; - client.OnViewerEffect -= ProcessViewerEffect; - } - - /// - /// Teleport an avatar to their home region - /// - /// The avatar's Unique ID - /// The IClientAPI for the client - public virtual bool TeleportClientHome(UUID agentId, IClientAPI client) - { - if (EntityTransferModule != null) - { - return EntityTransferModule.TeleportHome(agentId, client); - } - else - { - m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); - client.SendTeleportFailed("Unable to perform teleports on this simulator."); - } - return false; - } - - /// - /// Duplicates object specified by localID. This is the event handler for IClientAPI. - /// - /// ID of object to duplicate - /// - /// - /// Agent doing the duplication - /// Group of new object - public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID) - { - SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Identity); - if (copy != null) + return false; + } + + /// + /// Duplicates object specified by localID. This is the event handler for IClientAPI. + /// + /// ID of object to duplicate + /// + /// + /// Agent doing the duplication + /// Group of new object + public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID) + { + SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Identity); + if (copy != null) EventManager.TriggerObjectAddedToScene(copy); - } - - /// - /// Duplicates object specified by localID at position raycasted against RayTargetObject using - /// RayEnd and RayStart to determine what the angle of the ray is - /// - /// ID of object to duplicate - /// - /// Agent doing the duplication - /// Group of new object - /// The target of the Ray - /// The ending of the ray (farthest away point) - /// The Beginning of the ray (closest point) - /// Bool to bypass raycasting - /// The End specified is the place to add the object - /// Position the object at the center of the face that it's colliding with - /// Rotate the object the same as the localID object - public void doObjectDuplicateOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, - UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart, - bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) - { - Vector3 pos; - const bool frontFacesOnly = true; - //m_log.Info("HITTARGET: " + RayTargetObj.ToString() + ", COPYTARGET: " + localID.ToString()); - SceneObjectPart target = GetSceneObjectPart(localID); - SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj); - - if (target != null && target2 != null) - { - Vector3 direction = Vector3.Normalize(RayEnd - RayStart); - Vector3 AXOrigin = RayStart; - Vector3 AXdirection = direction; - - pos = target2.AbsolutePosition; - //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); - - // TODO: Raytrace better here - - //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); - Ray NewRay = new Ray(AXOrigin, AXdirection); - - // Ray Trace against target here - EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters); - - // Un-comment out the following line to Get Raytrace results printed to the console. - //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); - float ScaleOffset = 0.5f; - - // If we hit something - if (ei.HitTF) - { - Vector3 scale = target.Scale; - Vector3 scaleComponent = ei.AAfaceNormal; - if (scaleComponent.X != 0) ScaleOffset = scale.X; - if (scaleComponent.Y != 0) ScaleOffset = scale.Y; - if (scaleComponent.Z != 0) ScaleOffset = scale.Z; - ScaleOffset = Math.Abs(ScaleOffset); - Vector3 intersectionpoint = ei.ipoint; - Vector3 normal = ei.normal; - Vector3 offset = normal * (ScaleOffset / 2f); - pos = intersectionpoint + offset; - - // stick in offset format from the original prim - pos = pos - target.ParentGroup.AbsolutePosition; - SceneObjectGroup copy; - if (CopyRotates) - { - Quaternion worldRot = target2.GetWorldRotation(); - - // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); - copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); - //obj.Rotation = worldRot; - //obj.UpdateGroupRotationR(worldRot); - } - else - { - copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); - } - - if (copy != null) - EventManager.TriggerObjectAddedToScene(copy); - } - } - } - - /// - /// Get the avatar apperance for the given client. - /// - /// - /// - public void GetAvatarAppearance(IClientAPI client, out AvatarAppearance appearance) - { - AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); - - if (aCircuit == null) - { - m_log.DebugFormat("[APPEARANCE] Client did not supply a circuit. Non-Linden? Creating default appearance."); - appearance = new AvatarAppearance(); - return; - } - - appearance = aCircuit.Appearance; - if (appearance == null) - { - m_log.DebugFormat("[APPEARANCE]: Appearance not found in {0}, returning default", RegionInfo.RegionName); - appearance = new AvatarAppearance(); - } - } - - /// - /// Remove the given client from the scene. - /// - /// - /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead - /// to properly operate the state machine and avoid race conditions with other close requests (such as directly - /// from viewers). - /// - /// ID of agent to close - /// - /// Close the neighbour child agents associated with this client. - /// - public void RemoveClient(UUID agentID, bool closeChildAgents) - { - AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); - - // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which - // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not - // However, will keep for now just in case. - if (acd == null) - { - m_log.ErrorFormat( - "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name); - - return; - } - - // TODO: Can we now remove this lock? - lock (acd) - { - bool isChildAgent = false; - - ScenePresence avatar = GetScenePresence(agentID); + } + + /// + /// Duplicates object specified by localID at position raycasted against RayTargetObject using + /// RayEnd and RayStart to determine what the angle of the ray is + /// + /// ID of object to duplicate + /// + /// Agent doing the duplication + /// Group of new object + /// The target of the Ray + /// The ending of the ray (farthest away point) + /// The Beginning of the ray (closest point) + /// Bool to bypass raycasting + /// The End specified is the place to add the object + /// Position the object at the center of the face that it's colliding with + /// Rotate the object the same as the localID object + public void doObjectDuplicateOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, + UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart, + bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) + { + Vector3 pos; + const bool frontFacesOnly = true; + //m_log.Info("HITTARGET: " + RayTargetObj.ToString() + ", COPYTARGET: " + localID.ToString()); + SceneObjectPart target = GetSceneObjectPart(localID); + SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj); + + if (target != null && target2 != null) + { + Vector3 direction = Vector3.Normalize(RayEnd - RayStart); + Vector3 AXOrigin = RayStart; + Vector3 AXdirection = direction; + + pos = target2.AbsolutePosition; + //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); + + // TODO: Raytrace better here + + //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); + Ray NewRay = new Ray(AXOrigin, AXdirection); + + // Ray Trace against target here + EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters); + + // Un-comment out the following line to Get Raytrace results printed to the console. + //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); + float ScaleOffset = 0.5f; + + // If we hit something + if (ei.HitTF) + { + Vector3 scale = target.Scale; + Vector3 scaleComponent = ei.AAfaceNormal; + if (scaleComponent.X != 0) ScaleOffset = scale.X; + if (scaleComponent.Y != 0) ScaleOffset = scale.Y; + if (scaleComponent.Z != 0) ScaleOffset = scale.Z; + ScaleOffset = Math.Abs(ScaleOffset); + Vector3 intersectionpoint = ei.ipoint; + Vector3 normal = ei.normal; + Vector3 offset = normal * (ScaleOffset / 2f); + pos = intersectionpoint + offset; + + // stick in offset format from the original prim + pos = pos - target.ParentGroup.AbsolutePosition; + SceneObjectGroup copy; + if (CopyRotates) + { + Quaternion worldRot = target2.GetWorldRotation(); + + // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); + copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); + //obj.Rotation = worldRot; + //obj.UpdateGroupRotationR(worldRot); + } + else + { + copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); + } + + if (copy != null) + EventManager.TriggerObjectAddedToScene(copy); + } + } + } + + /// + /// Get the avatar apperance for the given client. + /// + /// + /// + public void GetAvatarAppearance(IClientAPI client, out AvatarAppearance appearance) + { + AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); + + if (aCircuit == null) + { + m_log.DebugFormat("[APPEARANCE] Client did not supply a circuit. Non-Linden? Creating default appearance."); + appearance = new AvatarAppearance(); + return; + } + + appearance = aCircuit.Appearance; + if (appearance == null) + { + m_log.DebugFormat("[APPEARANCE]: Appearance not found in {0}, returning default", RegionInfo.RegionName); + appearance = new AvatarAppearance(); + } + } + + /// + /// Remove the given client from the scene. + /// + /// + /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead + /// to properly operate the state machine and avoid race conditions with other close requests (such as directly + /// from viewers). + /// + /// ID of agent to close + /// + /// Close the neighbour child agents associated with this client. + /// + public void RemoveClient(UUID agentID, bool closeChildAgents) + { + AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not // However, will keep for now just in case. - if (avatar == null) + if (acd == null) { - m_log.ErrorFormat( - "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); - m_authenticateHandler.RemoveCircuit(agentID); + m_log.ErrorFormat( + "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name); + + return; + } + + // TODO: Can we now remove this lock? + lock (acd) + { + bool isChildAgent = false; + + ScenePresence avatar = GetScenePresence(agentID); + + // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which + // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not + // However, will keep for now just in case. + if (avatar == null) + { + m_log.ErrorFormat( + "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); + m_authenticateHandler.RemoveCircuit(agentID); + + return; + } + + try + { + isChildAgent = avatar.IsChildAgent; + + m_log.DebugFormat( + "[SCENE]: Removing {0} agent {1} {2} from {3}", + isChildAgent ? "child" : "root", avatar.Name, agentID, Name); + + // Don't do this to root agents, it's not nice for the viewer + if (closeChildAgents && isChildAgent) + { + // Tell a single agent to disconnect from the region. + // Let's do this via UDP + avatar.ControllingClient.SendShutdownConnectionNotice(); + } + + // Only applies to root agents. + if (avatar.ParentID != 0) + { + avatar.StandUp(); + } + + m_sceneGraph.removeUserCount(!isChildAgent); + + // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop + // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI + if (closeChildAgents && CapsModule != null) + CapsModule.RemoveCaps(agentID); + + if (closeChildAgents && !isChildAgent) + { + List regions = avatar.KnownRegionHandles; + regions.Remove(RegionInfo.RegionHandle); + + // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours. + m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions); + } + + m_eventManager.TriggerClientClosed(agentID, this); + m_eventManager.TriggerOnRemovePresence(agentID); + + if (!isChildAgent) + { + if (AttachmentsModule != null) + { + AttachmentsModule.DeRezAttachments(avatar); + } + + ForEachClient( + delegate(IClientAPI client) + { + //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway + try { client.SendKillObject(new List { avatar.LocalId }); } + catch (NullReferenceException) { } + }); + } + + // It's possible for child agents to have transactions if changes are being made cross-border. + if (AgentTransactionsModule != null) + AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); + } + catch (Exception e) + { + m_log.Error( + string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); + } + finally + { + try + { + // Always clean these structures up so that any failure above doesn't cause them to remain in the + // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering + // the same cleanup exception continually. + m_authenticateHandler.RemoveCircuit(agentID); + m_sceneGraph.RemoveScenePresence(agentID); + m_clientManager.Remove(agentID); + + avatar.Close(); + } + catch (Exception e) + { + m_log.Error( + string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); + } + } + } + + //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); + //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); + } + + /// + /// Removes region from an avatar's known region list. This coincides with child agents. For each child agent, there will be a known region entry. + /// + /// + /// + /// + public void HandleRemoveKnownRegionsFromAvatar(UUID avatarID, List regionslst) + { + ScenePresence av = GetScenePresence(avatarID); + if (av != null) + { + lock (av) + { + for (int i = 0; i < regionslst.Count; i++) + { + av.RemoveNeighbourRegion(regionslst[i]); + } + } + } + } + + #endregion + + #region Entities + + public void SendKillObject(List localIDs) + { + List deleteIDs = new List(); + + foreach (uint localID in localIDs) + { + SceneObjectPart part = GetSceneObjectPart(localID); + if (part != null) // It is a prim + { + if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid + { + if (part.ParentGroup.RootPart != part) // Child part + continue; + } + } + deleteIDs.Add(localID); + } + + ForEachClient(c => c.SendKillObject(deleteIDs)); + } + + #endregion + + #region RegionComms + + /// + /// Do the work necessary to initiate a new user connection for a particular scene. + /// + /// CircuitData of the agent who is connecting + /// + /// Source region (may be null) + /// Outputs the reason for the false response on this string + /// True if the region accepts this agent. False if it does not. False will + /// also return a reason. + public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason) + { + return NewUserConnection(agent, teleportFlags, source, out reason, true); + } + + /// + /// Do the work necessary to initiate a new user connection for a particular scene. + /// + /// + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it yet, we still allowed banned users in. + /// + /// At the moment this method consists of setting up the caps infrastructure + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it let, we allowed banned users in still. + /// + /// This method is called by the login service (in the case of login) or another simulator (in the case of region + /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection + /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of + /// the LLUDP stack). + /// + /// CircuitData of the agent who is connecting + /// Source region (may be null) + /// Outputs the reason for the false response on this string + /// True for normal presence. False for NPC + /// or other applications where a full grid/Hypergrid presence may not be required. + /// True if the region accepts this agent. False if it does not. False will + /// also return a reason. + public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup) + { + bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || + (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); + bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0); + bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0); - return; + reason = String.Empty; + + //Teleport flags: + // + // TeleportFlags.ViaGodlikeLure - Border Crossing + // TeleportFlags.ViaLogin - Login + // TeleportFlags.TeleportFlags.ViaLure - Teleport request sent by another user + // TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport + + // Don't disable this log message - it's too helpful + string curViewer = Util.GetViewerName(acd); + m_log.DebugFormat( + "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9}. {10}", + RegionInfo.RegionName, + (acd.child ? "child" : "root"), + acd.firstname, + acd.lastname, + acd.AgentID, + acd.circuitcode, + acd.IPAddress, + curViewer, + ((TPFlags)teleportFlags).ToString(), + acd.startpos, + (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI) + ); + + if (!LoginsEnabled) + { + reason = "Logins Disabled"; + return false; + } + + //Check if the viewer is banned or in the viewer access list + //We check if the substring is listed for higher flexebility + bool ViewerDenied = true; + + //Check if the specific viewer is listed in the allowed viewer list + if (m_AllowedViewers.Count > 0) + { + foreach (string viewer in m_AllowedViewers) + { + if (viewer == curViewer.Substring(0, Math.Min(viewer.Length, curViewer.Length)).Trim().ToLower()) + { + ViewerDenied = false; + break; + } + } + } + else + { + ViewerDenied = false; } - try + //Check if the viewer is in the banned list + if (m_BannedViewers.Count > 0) { - isChildAgent = avatar.IsChildAgent; - - m_log.DebugFormat( - "[SCENE]: Removing {0} agent {1} {2} from {3}", - isChildAgent ? "child" : "root", avatar.Name, agentID, Name); - - // Don't do this to root agents, it's not nice for the viewer - if (closeChildAgents && isChildAgent) - { - // Tell a single agent to disconnect from the region. - // Let's do this via UDP - avatar.ControllingClient.SendShutdownConnectionNotice(); - } - - // Only applies to root agents. - if (avatar.ParentID != 0) - { - avatar.StandUp(); - } - - m_sceneGraph.removeUserCount(!isChildAgent); - - // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop - // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI - if (closeChildAgents && CapsModule != null) - CapsModule.RemoveCaps(agentID); - - if (closeChildAgents && !isChildAgent) - { - List regions = avatar.KnownRegionHandles; - regions.Remove(RegionInfo.RegionHandle); - - // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours. - m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions); - } - - m_eventManager.TriggerClientClosed(agentID, this); - m_eventManager.TriggerOnRemovePresence(agentID); - - if (!isChildAgent) - { - if (AttachmentsModule != null) - { - AttachmentsModule.DeRezAttachments(avatar); - } - - ForEachClient( - delegate(IClientAPI client) - { - //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway - try { client.SendKillObject(new List { avatar.LocalId }); } - catch (NullReferenceException) { } - }); - } - - // It's possible for child agents to have transactions if changes are being made cross-border. - if (AgentTransactionsModule != null) - AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); + foreach (string viewer in m_BannedViewers) + { + if (viewer == curViewer.Substring(0, Math.Min(viewer.Length, curViewer.Length)).Trim().ToLower()) + { + ViewerDenied = true; + break; + } + } } - catch (Exception e) + + if (ViewerDenied) { - m_log.Error( - string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); - } - finally - { - try - { - // Always clean these structures up so that any failure above doesn't cause them to remain in the - // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering - // the same cleanup exception continually. - m_authenticateHandler.RemoveCircuit(agentID); - m_sceneGraph.RemoveScenePresence(agentID); - m_clientManager.Remove(agentID); - - avatar.Close(); - } - catch (Exception e) - { - m_log.Error( - string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); - } - } - } - - //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); - //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); - } - - /// - /// Removes region from an avatar's known region list. This coincides with child agents. For each child agent, there will be a known region entry. - /// - /// - /// - /// - public void HandleRemoveKnownRegionsFromAvatar(UUID avatarID, List regionslst) - { - ScenePresence av = GetScenePresence(avatarID); - if (av != null) - { - lock (av) - { - for (int i = 0; i < regionslst.Count; i++) - { - av.RemoveNeighbourRegion(regionslst[i]); - } - } - } - } - - #endregion - - #region Entities - - public void SendKillObject(List localIDs) - { - List deleteIDs = new List(); - - foreach (uint localID in localIDs) - { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null) // It is a prim - { - if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid - { - if (part.ParentGroup.RootPart != part) // Child part - continue; - } - } - deleteIDs.Add(localID); - } - - ForEachClient(c => c.SendKillObject(deleteIDs)); - } - - #endregion - - #region RegionComms - - /// - /// Do the work necessary to initiate a new user connection for a particular scene. - /// - /// CircuitData of the agent who is connecting - /// - /// Source region (may be null) - /// Outputs the reason for the false response on this string - /// True if the region accepts this agent. False if it does not. False will - /// also return a reason. - public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason) - { - return NewUserConnection(agent, teleportFlags, source, out reason, true); - } - - /// - /// Do the work necessary to initiate a new user connection for a particular scene. - /// - /// - /// The return bool should allow for connections to be refused, but as not all calling paths - /// take proper notice of it yet, we still allowed banned users in. - /// - /// At the moment this method consists of setting up the caps infrastructure - /// The return bool should allow for connections to be refused, but as not all calling paths - /// take proper notice of it let, we allowed banned users in still. - /// - /// This method is called by the login service (in the case of login) or another simulator (in the case of region - /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection - /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of - /// the LLUDP stack). - /// - /// CircuitData of the agent who is connecting - /// Source region (may be null) - /// Outputs the reason for the false response on this string - /// True for normal presence. False for NPC - /// or other applications where a full grid/Hypergrid presence may not be required. - /// True if the region accepts this agent. False if it does not. False will - /// also return a reason. - public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup) - { - bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || - (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); - bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0); - bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0); - - reason = String.Empty; - - //Teleport flags: - // - // TeleportFlags.ViaGodlikeLure - Border Crossing - // TeleportFlags.ViaLogin - Login - // TeleportFlags.TeleportFlags.ViaLure - Teleport request sent by another user - // TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport - - // Don't disable this log message - it's too helpful - string curViewer = Util.GetViewerName(acd); - m_log.DebugFormat( - "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9}. {10}", - RegionInfo.RegionName, - (acd.child ? "child" : "root"), - acd.firstname, - acd.lastname, - acd.AgentID, - acd.circuitcode, - acd.IPAddress, - curViewer, - ((TPFlags)teleportFlags).ToString(), - acd.startpos, - (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI) - ); - - if (!LoginsEnabled) - { - reason = "Logins Disabled"; - return false; - } - - //Check if the viewer is banned or in the viewer access list - //We check if the substring is listed for higher flexebility - bool ViewerDenied = true; - - //Check if the specific viewer is listed in the allowed viewer list - if (m_AllowedViewers.Count > 0) - { - foreach (string viewer in m_AllowedViewers) - { - if (viewer == curViewer.Substring(0, Math.Min(viewer.Length, curViewer.Length)).Trim().ToLower()) - { - ViewerDenied = false; - break; - } - } - } - else - { - ViewerDenied = false; - } - - //Check if the viewer is in the banned list - if (m_BannedViewers.Count > 0) - { - foreach (string viewer in m_BannedViewers) - { - if (viewer == curViewer.Substring(0, Math.Min(viewer.Length, curViewer.Length)).Trim().ToLower()) - { - ViewerDenied = true; - break; - } - } - } - - if (ViewerDenied) - { - m_log.DebugFormat( + m_log.DebugFormat( "[SCENE]: Access denied for {0} {1} using {2}", acd.firstname, acd.lastname, curViewer); - reason = "Access denied, your viewer is banned by the region owner"; - return false; - } - - ILandObject land; - ScenePresence sp; - - lock (m_removeClientLock) - { - sp = GetScenePresence(acd.AgentID); - - // We need to ensure that we are not already removing the scene presence before we ask it not to be - // closed. - if (sp != null && sp.IsChildAgent - && (sp.LifecycleState == ScenePresenceState.Running - || sp.LifecycleState == ScenePresenceState.PreRemove)) - { - m_log.DebugFormat( - "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}", - sp.Name, sp.LifecycleState, Name); - - // In the case where, for example, an A B C D region layout, an avatar may - // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C - // renews the lease on the child agent at B, we must make sure that the close from A does not succeed. - // - // XXX: In the end, this should not be necessary if child agents are closed without delay on - // teleport, since realistically, the close request should always be processed before any other - // region tried to re-establish a child agent. This is much simpler since the logic below is - // vulnerable to an issue when a viewer quits a region without sending a proper logout but then - // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport - // flag when no teleport had taken place (and hence no close was going to come). - // if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle)) - // { - // m_log.DebugFormat( - // "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.", - // sp.Name, Name); - // - // sp.DoNotCloseAfterTeleport = true; - // } - // else if (EntityTransferModule.IsInTransit(sp.UUID)) - - sp.LifecycleState = ScenePresenceState.Running; - - if (EntityTransferModule.IsInTransit(sp.UUID)) - { - sp.DoNotCloseAfterTeleport = true; - - m_log.DebugFormat( - "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.", - sp.Name, Name); - } - } - } - - // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will - // allow unpredictable things to happen. - if (sp != null) - { - const int polls = 10; - const int pollInterval = 1000; - int pollsLeft = polls; - - while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0) - Thread.Sleep(pollInterval); - - if (sp.LifecycleState == ScenePresenceState.Removing) - { - m_log.WarnFormat( - "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.", - sp.Name, Name, polls * pollInterval / 1000); - - return false; - } - else if (polls != pollsLeft) - { - m_log.DebugFormat( - "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.", - sp.Name, Name, polls * pollInterval / 1000); - } - } - - // TODO: can we remove this lock? - lock (acd) - { - if (sp != null && !sp.IsChildAgent) - { - // We have a root agent. Is it in transit? - if (!EntityTransferModule.IsInTransit(sp.UUID)) - { - // We have a zombie from a crashed session. - // Or the same user is trying to be root twice here, won't work. - // Kill it. - m_log.WarnFormat( - "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", - sp.Name, sp.UUID, RegionInfo.RegionName); - - if (sp.ControllingClient != null) - CloseAgent(sp.UUID, true); - - sp = null; - } - //else - // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName); - } - - // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags. - // We need the circuit data here for some of the subsequent checks. (groups, for example) - // If the checks fail, we remove the circuit. - acd.teleportFlags = teleportFlags; - m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); - - land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y); - - // On login test land permisions - if (vialogin) + reason = "Access denied, your viewer is banned by the region owner"; + return false; + } + + ILandObject land; + ScenePresence sp; + + lock (m_removeClientLock) + { + sp = GetScenePresence(acd.AgentID); + + // We need to ensure that we are not already removing the scene presence before we ask it not to be + // closed. + if (sp != null && sp.IsChildAgent + && (sp.LifecycleState == ScenePresenceState.Running + || sp.LifecycleState == ScenePresenceState.PreRemove)) + { + m_log.DebugFormat( + "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}", + sp.Name, sp.LifecycleState, Name); + + // In the case where, for example, an A B C D region layout, an avatar may + // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C + // renews the lease on the child agent at B, we must make sure that the close from A does not succeed. + // + // XXX: In the end, this should not be necessary if child agents are closed without delay on + // teleport, since realistically, the close request should always be processed before any other + // region tried to re-establish a child agent. This is much simpler since the logic below is + // vulnerable to an issue when a viewer quits a region without sending a proper logout but then + // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport + // flag when no teleport had taken place (and hence no close was going to come). + // if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle)) + // { + // m_log.DebugFormat( + // "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.", + // sp.Name, Name); + // + // sp.DoNotCloseAfterTeleport = true; + // } + // else if (EntityTransferModule.IsInTransit(sp.UUID)) + + sp.LifecycleState = ScenePresenceState.Running; + + if (EntityTransferModule.IsInTransit(sp.UUID)) + { + sp.DoNotCloseAfterTeleport = true; + + m_log.DebugFormat( + "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.", + sp.Name, Name); + } + } + } + + // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will + // allow unpredictable things to happen. + if (sp != null) { - if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - } + const int polls = 10; + const int pollInterval = 1000; + int pollsLeft = polls; + + while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0) + Thread.Sleep(pollInterval); + + if (sp.LifecycleState == ScenePresenceState.Removing) + { + m_log.WarnFormat( + "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.", + sp.Name, Name, polls * pollInterval / 1000); + + return false; + } + else if (polls != pollsLeft) + { + m_log.DebugFormat( + "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.", + sp.Name, Name, polls * pollInterval / 1000); + } + } + + // TODO: can we remove this lock? + lock (acd) + { + if (sp != null && !sp.IsChildAgent) + { + // We have a root agent. Is it in transit? + if (!EntityTransferModule.IsInTransit(sp.UUID)) + { + // We have a zombie from a crashed session. + // Or the same user is trying to be root twice here, won't work. + // Kill it. + m_log.WarnFormat( + "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", + sp.Name, sp.UUID, RegionInfo.RegionName); + + if (sp.ControllingClient != null) + CloseAgent(sp.UUID, true); + + sp = null; + } + //else + // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName); + } + + // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags. + // We need the circuit data here for some of the subsequent checks. (groups, for example) + // If the checks fail, we remove the circuit. + acd.teleportFlags = teleportFlags; + m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); + + land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y); + + // On login test land permisions + if (vialogin) + { + if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) + { + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + } + + if (sp == null) // We don't have an [child] agent here already + { + if (requirePresenceLookup) + { + try + { + if (!VerifyUserPresence(acd, out reason)) + { + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + } + catch (Exception e) + { + m_log.ErrorFormat( + "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); + + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + } + + try + { + if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason)) + { + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + } + catch (Exception e) + { + m_log.ErrorFormat( + "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); - if (sp == null) // We don't have an [child] agent here already - { - if (requirePresenceLookup) - { - try - { - if (!VerifyUserPresence(acd, out reason)) - { m_authenticateHandler.RemoveCircuit(acd.circuitcode); return false; - } - } - catch (Exception e) - { - m_log.ErrorFormat( - "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); - - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - } - - try - { - if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - } - catch (Exception e) - { - m_log.ErrorFormat( - "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); - - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - - m_log.InfoFormat( - "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", - Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname, - acd.AgentID, acd.circuitcode); - - if (CapsModule != null) - { - CapsModule.SetAgentCapsSeeds(acd); - CapsModule.CreateCaps(acd.AgentID); - } + } + + m_log.InfoFormat( + "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", + Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname, + acd.AgentID, acd.circuitcode); + + if (CapsModule != null) + { + CapsModule.SetAgentCapsSeeds(acd); + CapsModule.CreateCaps(acd.AgentID); + } + } + else + { + // Let the SP know how we got here. This has a lot of interesting + // uses down the line. + sp.TeleportFlags = (TPFlags)teleportFlags; + + if (sp.IsChildAgent) + { + m_log.DebugFormat( + "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", + acd.AgentID, RegionInfo.RegionName); + + sp.AdjustKnownSeeds(); + + if (CapsModule != null) + { + CapsModule.SetAgentCapsSeeds(acd); + CapsModule.CreateCaps(acd.AgentID); + } + } + } + + // Try caching an incoming user name much earlier on to see if this helps with an issue + // where HG users are occasionally seen by others as "Unknown User" because their UUIDName + // request for the HG avatar appears to trigger before the user name is cached. + CacheUserName(null, acd); } - else + + if (vialogin) { - // Let the SP know how we got here. This has a lot of interesting - // uses down the line. - sp.TeleportFlags = (TPFlags)teleportFlags; - - if (sp.IsChildAgent) - { - m_log.DebugFormat( - "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", - acd.AgentID, RegionInfo.RegionName); - - sp.AdjustKnownSeeds(); - - if (CapsModule != null) - { - CapsModule.SetAgentCapsSeeds(acd); - CapsModule.CreateCaps(acd.AgentID); - } - } - } - - // Try caching an incoming user name much earlier on to see if this helps with an issue - // where HG users are occasionally seen by others as "Unknown User" because their UUIDName - // request for the HG avatar appears to trigger before the user name is cached. - CacheUserName(null, acd); - } - - if (vialogin) - { - // CleanDroppedAttachments(); - - // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking) - if (acd.startpos.X < 0) acd.startpos.X = 1f; - if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f; - if (acd.startpos.Y < 0) acd.startpos.Y = 1f; - if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f; - - // m_log.DebugFormat( - // "[SCENE]: Found telehub object {0} for new user connection {1} to {2}", - // RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); - - // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags - if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && - RegionInfo.EstateSettings.AllowDirectTeleport == false && - !viahome && !godlike) - { - SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); - - if (telehub != null) - { - // Can have multiple SpawnPoints - List spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); - if (spawnpoints.Count > 1) - { - // We have multiple SpawnPoints, Route the agent to a random or sequential one - if (SpawnPointRouting == "random") - acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( + // CleanDroppedAttachments(); + + // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking) + if (acd.startpos.X < 0) acd.startpos.X = 1f; + if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f; + if (acd.startpos.Y < 0) acd.startpos.Y = 1f; + if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f; + + // m_log.DebugFormat( + // "[SCENE]: Found telehub object {0} for new user connection {1} to {2}", + // RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); + + // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags + if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && + RegionInfo.EstateSettings.AllowDirectTeleport == false && + !viahome && !godlike) + { + SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); + + if (telehub != null) + { + // Can have multiple SpawnPoints + List spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); + if (spawnpoints.Count > 1) + { + // We have multiple SpawnPoints, Route the agent to a random or sequential one + if (SpawnPointRouting == "random") + acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( telehub.AbsolutePosition, telehub.GroupRotation - ); - else - acd.startpos = spawnpoints[SpawnPoint()].GetLocation( + ); + else + acd.startpos = spawnpoints[SpawnPoint()].GetLocation( telehub.AbsolutePosition, telehub.GroupRotation - ); - } - else if (spawnpoints.Count == 1) - { - // We have a single SpawnPoint and will route the agent to it - acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); - } - else - { - m_log.DebugFormat( - "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.", - RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); - } - } - else - { - m_log.DebugFormat( - "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.", - RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); - } - - // Final permissions check; this time we don't allow changing the position - if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - - return true; - } - - // Honor parcel landing type and position. - if (land != null) - { - if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) - { - acd.startpos = land.LandData.UserLocation; - - // Final permissions check; this time we don't allow changing the position - if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - } - } - } - - return true; - } - - private bool IsPositionAllowed(UUID agentID, Vector3 pos, ref string reason) - { - ILandObject land = LandChannel.GetLandObject(pos); - if (land == null) + ); + } + else if (spawnpoints.Count == 1) + { + // We have a single SpawnPoint and will route the agent to it + acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + } + else + { + m_log.DebugFormat( + "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.", + RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); + } + } + else + { + m_log.DebugFormat( + "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.", + RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); + } + + // Final permissions check; this time we don't allow changing the position + if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) + { + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + + return true; + } + + // Honor parcel landing type and position. + if (land != null) + { + if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) + { + acd.startpos = land.LandData.UserLocation; + + // Final permissions check; this time we don't allow changing the position + if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) + { + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; + } + } + } + } + return true; + } - if (land.IsBannedFromLand(agentID) || land.IsRestrictedFromLand(agentID)) - { - reason = "You are banned from the region."; - return false; - } + private bool IsPositionAllowed(UUID agentID, Vector3 pos, ref string reason) + { + ILandObject land = LandChannel.GetLandObject(pos); + if (land == null) + return true; + + if (land.IsBannedFromLand(agentID) || land.IsRestrictedFromLand(agentID)) + { + reason = "You are banned from the region."; + return false; + } - return true; - } + return true; + } - public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY) - { - if (posX < 0) + public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY) + { + if (posX < 0) posX = 0; - else if (posX >= (float)RegionInfo.RegionSizeX) + else if (posX >= (float)RegionInfo.RegionSizeX) posX = (float)RegionInfo.RegionSizeX - 0.001f; - if (posY < 0) + if (posY < 0) posY = 0; - else if (posY >= (float)RegionInfo.RegionSizeY) + else if (posY >= (float)RegionInfo.RegionSizeY) posY = (float)RegionInfo.RegionSizeY - 0.001f; - reason = String.Empty; - if (Permissions.IsGod(agentID)) + reason = String.Empty; + if (Permissions.IsGod(agentID)) return true; - ILandObject land = LandChannel.GetLandObject(posX, posY); - if (land == null) + ILandObject land = LandChannel.GetLandObject(posX, posY); + if (land == null) return false; - bool banned = land.IsBannedFromLand(agentID); - bool restricted = land.IsRestrictedFromLand(agentID); + bool banned = land.IsBannedFromLand(agentID); + bool restricted = land.IsRestrictedFromLand(agentID); - if (banned || restricted) - { - ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY); - if (nearestParcel != null) + if (banned || restricted) { - //Move agent to nearest allowed - Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); - posX = newPosition.X; - posY = newPosition.Y; - } - else + ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY); + if (nearestParcel != null) + { + //Move agent to nearest allowed + Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); + posX = newPosition.X; + posY = newPosition.Y; + } + else + { + if (banned) + { + reason = "Cannot regioncross into banned parcel."; + } + else + { + reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", + RegionInfo.RegionName); + } + return false; + } + } + reason = ""; + return true; + } + + /// + /// Verifies that the user has a presence on the Grid + /// + /// Circuit Data of the Agent we're verifying + /// Outputs the reason for the false response on this string + /// True if the user has a session on the grid. False if it does not. False will + /// also return a reason. + public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason) + { + reason = String.Empty; + + IPresenceService presence = RequestModuleInterface(); + if (presence == null) { - if (banned) - { - reason = "Cannot regioncross into banned parcel."; - } - else - { - reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", - RegionInfo.RegionName); - } - return false; - } - } - reason = ""; - return true; - } - - /// - /// Verifies that the user has a presence on the Grid - /// - /// Circuit Data of the Agent we're verifying - /// Outputs the reason for the false response on this string - /// True if the user has a session on the grid. False if it does not. False will - /// also return a reason. - public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason) - { - reason = String.Empty; - - IPresenceService presence = RequestModuleInterface(); - if (presence == null) - { - reason = String.Format("Failed to verify user presence in the grid for {0} {1} in region {2}. Presence service does not exist.", agent.firstname, agent.lastname, RegionInfo.RegionName); - return false; - } + reason = String.Format("Failed to verify user presence in the grid for {0} {1} in region {2}. Presence service does not exist.", agent.firstname, agent.lastname, RegionInfo.RegionName); + return false; + } - OpenSim.Services.Interfaces.PresenceInfo pinfo = presence.GetAgent(agent.SessionID); + OpenSim.Services.Interfaces.PresenceInfo pinfo = presence.GetAgent(agent.SessionID); - if (pinfo == null) - { - reason = String.Format("Failed to verify user presence in the grid for {0} {1}, access denied to region {2}.", agent.firstname, agent.lastname, RegionInfo.RegionName); - return false; - } - - return true; - } - - /// - /// Verify if the user can connect to this region. Checks the banlist and ensures that the region is set for public access - /// - /// The circuit data for the agent - /// outputs the reason to this string - /// True if the region accepts this agent. False if it does not. False will - /// also return a reason. - protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason) - { - reason = String.Empty; - - if (!m_strictAccessControl) return true; - if (Permissions.IsGod(agent.AgentID)) return true; - - if (AuthorizationService != null) - { - if (!AuthorizationService.IsAuthorizedForRegion( - agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason)) - { - m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because: {4}", - agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName, reason); - - return false; - } - } - - // We only test the things below when we want to cut off - // child agents from being present in the scene for which their root - // agent isn't allowed. Otherwise, we allow child agents. The test for - // the root is done elsewhere (QueryAccess) - if (!bypassAccessControl) - { - if (RegionInfo.EstateSettings != null) - { - if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) - { - m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", - agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - reason = String.Format("Denied access to region {0}: You have been banned from that region.", - RegionInfo.RegionName); - return false; - } - } - else + if (pinfo == null) { - m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); + reason = String.Format("Failed to verify user presence in the grid for {0} {1}, access denied to region {2}.", agent.firstname, agent.lastname, RegionInfo.RegionName); + return false; } - List agentGroups = new List(); + return true; + } + + /// + /// Verify if the user can connect to this region. Checks the banlist and ensures that the region is set for public access + /// + /// The circuit data for the agent + /// outputs the reason to this string + /// True if the region accepts this agent. False if it does not. False will + /// also return a reason. + protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason) + { + reason = String.Empty; + + if (!m_strictAccessControl) return true; + if (Permissions.IsGod(agent.AgentID)) return true; - if (m_groupsModule != null) + if (AuthorizationService != null) { - GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); + if (!AuthorizationService.IsAuthorizedForRegion( + agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason)) + { + m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because: {4}", + agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName, reason); - if (GroupMembership != null) - { - for (int i = 0; i < GroupMembership.Length; i++) - agentGroups.Add(GroupMembership[i].GroupID); - } - else - { - m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); - } + return false; + } } - bool groupAccess = false; - UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; - - if (estateGroups != null) + // We only test the things below when we want to cut off + // child agents from being present in the scene for which their root + // agent isn't allowed. Otherwise, we allow child agents. The test for + // the root is done elsewhere (QueryAccess) + if (!bypassAccessControl) { - foreach (UUID group in estateGroups) - { - if (agentGroups.Contains(group)) - { - groupAccess = true; - break; - } - } - } - else + if (RegionInfo.EstateSettings != null) + { + if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) + { + m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", + agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + reason = String.Format("Denied access to region {0}: You have been banned from that region.", + RegionInfo.RegionName); + return false; + } + } + else + { + m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); + } + + List agentGroups = new List(); + + if (m_groupsModule != null) + { + GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); + + if (GroupMembership != null) + { + for (int i = 0; i < GroupMembership.Length; i++) + agentGroups.Add(GroupMembership[i].GroupID); + } + else + { + m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); + } + } + + bool groupAccess = false; + UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; + + if (estateGroups != null) + { + foreach (UUID group in estateGroups) + { + if (agentGroups.Contains(group)) + { + groupAccess = true; + break; + } + } + } + else + { + m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); + } + + if (!RegionInfo.EstateSettings.PublicAccess && + !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && + !groupAccess) + { + m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", + agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", + RegionInfo.RegionName); + return false; + } + } + + // TODO: estate/region settings are not properly hooked up + // to ILandObject.isRestrictedFromLand() + // if (null != LandChannel) + // { + // // region seems to have local Id of 1 + // ILandObject land = LandChannel.GetLandObject(1); + // if (null != land) + // { + // if (land.isBannedFromLand(agent.AgentID)) + // { + // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land", + // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + // reason = String.Format("Denied access to private region {0}: You are banned from that region.", + // RegionInfo.RegionName); + // return false; + // } + + // if (land.isRestrictedFromLand(agent.AgentID)) + // { + // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", + // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", + // RegionInfo.RegionName); + // return false; + // } + // } + // } + + return true; + } + + /// + /// Update an AgentCircuitData object with new information + /// + /// Information to update the AgentCircuitData with + public void UpdateCircuitData(AgentCircuitData data) + { + m_authenticateHandler.UpdateAgentData(data); + } + + /// + /// Change the Circuit Code for the user's Circuit Data + /// + /// The old Circuit Code. Must match a previous circuit code + /// The new Circuit Code. Must not be an already existing circuit code + /// True if we successfully changed it. False if we did not + public bool ChangeCircuitCode(uint oldcc, uint newcc) + { + return m_authenticateHandler.TryChangeCiruitCode(oldcc, newcc); + } + + // /// + // /// The Grid has requested that we log-off a user. Log them off. + // /// + // /// Unique ID of the avatar to log-off + // /// SecureSessionID of the user, or the RegionSecret text when logging on to the grid + // /// message to display to the user. Reason for being logged off + // public void HandleLogOffUserFromGrid(UUID AvatarID, UUID RegionSecret, string message) + // { + // ScenePresence loggingOffUser = GetScenePresence(AvatarID); + // if (loggingOffUser != null) + // { + // UUID localRegionSecret = UUID.Zero; + // bool parsedsecret = UUID.TryParse(RegionInfo.regionSecret, out localRegionSecret); + // + // // Region Secret is used here in case a new sessionid overwrites an old one on the user server. + // // Will update the user server in a few revisions to use it. + // + // if (RegionSecret == loggingOffUser.ControllingClient.SecureSessionId || (parsedsecret && RegionSecret == localRegionSecret)) + // { + // m_sceneGridService.SendCloseChildAgentConnections(loggingOffUser.UUID, loggingOffUser.KnownRegionHandles); + // loggingOffUser.ControllingClient.Kick(message); + // // Give them a second to receive the message! + // Thread.Sleep(1000); + // loggingOffUser.ControllingClient.Close(); + // } + // else + // { + // m_log.Info("[USERLOGOFF]: System sending the LogOff user message failed to sucessfully authenticate"); + // } + // } + // else + // { + // m_log.InfoFormat("[USERLOGOFF]: Got a logoff request for {0} but the user isn't here. The user might already have been logged out", AvatarID.ToString()); + // } + // } + + // /// + // /// Triggered when an agent crosses into this sim. Also happens on initial login. + // /// + // /// + // /// + // /// + // public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying) + // { + // ScenePresence presence = GetScenePresence(agentID); + // if (presence != null) + // { + // try + // { + // presence.MakeRootAgent(position, isFlying); + // } + // catch (Exception e) + // { + // m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace); + // } + // } + // else + // { + // m_log.ErrorFormat( + // "[SCENE]: Could not find presence for agent {0} crossing into scene {1}", + // agentID, RegionInfo.RegionName); + // } + // } + + /// + /// We've got an update about an agent that sees into this region, + /// send it to ScenePresence for processing It's the full data. + /// + /// Agent that contains all of the relevant things about an agent. + /// Appearance, animations, position, etc. + /// true if we handled it. + public virtual bool IncomingUpdateChildAgent(AgentData cAgentData) + { + m_log.DebugFormat( + "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); + + // TODO: This check should probably be in QueryAccess(). + ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2); + if (nearestParcel == null) { - m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); - } - - if (!RegionInfo.EstateSettings.PublicAccess && - !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && - !groupAccess) - { - m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", - agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", - RegionInfo.RegionName); - return false; - } - } - - // TODO: estate/region settings are not properly hooked up - // to ILandObject.isRestrictedFromLand() - // if (null != LandChannel) - // { - // // region seems to have local Id of 1 - // ILandObject land = LandChannel.GetLandObject(1); - // if (null != land) - // { - // if (land.isBannedFromLand(agent.AgentID)) - // { - // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land", - // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - // reason = String.Format("Denied access to private region {0}: You are banned from that region.", - // RegionInfo.RegionName); - // return false; - // } - - // if (land.isRestrictedFromLand(agent.AgentID)) - // { - // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", - // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", - // RegionInfo.RegionName); - // return false; - // } - // } - // } - - return true; - } - - /// - /// Update an AgentCircuitData object with new information - /// - /// Information to update the AgentCircuitData with - public void UpdateCircuitData(AgentCircuitData data) - { - m_authenticateHandler.UpdateAgentData(data); - } - - /// - /// Change the Circuit Code for the user's Circuit Data - /// - /// The old Circuit Code. Must match a previous circuit code - /// The new Circuit Code. Must not be an already existing circuit code - /// True if we successfully changed it. False if we did not - public bool ChangeCircuitCode(uint oldcc, uint newcc) - { - return m_authenticateHandler.TryChangeCiruitCode(oldcc, newcc); - } - - // /// - // /// The Grid has requested that we log-off a user. Log them off. - // /// - // /// Unique ID of the avatar to log-off - // /// SecureSessionID of the user, or the RegionSecret text when logging on to the grid - // /// message to display to the user. Reason for being logged off - // public void HandleLogOffUserFromGrid(UUID AvatarID, UUID RegionSecret, string message) - // { - // ScenePresence loggingOffUser = GetScenePresence(AvatarID); - // if (loggingOffUser != null) - // { - // UUID localRegionSecret = UUID.Zero; - // bool parsedsecret = UUID.TryParse(RegionInfo.regionSecret, out localRegionSecret); - // - // // Region Secret is used here in case a new sessionid overwrites an old one on the user server. - // // Will update the user server in a few revisions to use it. - // - // if (RegionSecret == loggingOffUser.ControllingClient.SecureSessionId || (parsedsecret && RegionSecret == localRegionSecret)) - // { - // m_sceneGridService.SendCloseChildAgentConnections(loggingOffUser.UUID, loggingOffUser.KnownRegionHandles); - // loggingOffUser.ControllingClient.Kick(message); - // // Give them a second to receive the message! - // Thread.Sleep(1000); - // loggingOffUser.ControllingClient.Close(); - // } - // else - // { - // m_log.Info("[USERLOGOFF]: System sending the LogOff user message failed to sucessfully authenticate"); - // } - // } - // else - // { - // m_log.InfoFormat("[USERLOGOFF]: Got a logoff request for {0} but the user isn't here. The user might already have been logged out", AvatarID.ToString()); - // } - // } - - // /// - // /// Triggered when an agent crosses into this sim. Also happens on initial login. - // /// - // /// - // /// - // /// - // public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying) - // { - // ScenePresence presence = GetScenePresence(agentID); - // if (presence != null) - // { - // try - // { - // presence.MakeRootAgent(position, isFlying); - // } - // catch (Exception e) - // { - // m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace); - // } - // } - // else - // { - // m_log.ErrorFormat( - // "[SCENE]: Could not find presence for agent {0} crossing into scene {1}", - // agentID, RegionInfo.RegionName); - // } - // } - - /// - /// We've got an update about an agent that sees into this region, - /// send it to ScenePresence for processing It's the full data. - /// - /// Agent that contains all of the relevant things about an agent. - /// Appearance, animations, position, etc. - /// true if we handled it. - public virtual bool IncomingUpdateChildAgent(AgentData cAgentData) - { - m_log.DebugFormat( - "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); - - // TODO: This check should probably be in QueryAccess(). - ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2); - if (nearestParcel == null) - { - m_log.InfoFormat( + m_log.InfoFormat( "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", cAgentData.AgentID, RegionInfo.RegionName); - return false; - } + return false; + } - // We have to wait until the viewer contacts this region - // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol) - // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send - // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. - ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); + // We have to wait until the viewer contacts this region + // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol) + // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send + // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. + ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); - if (sp != null) - { - if (cAgentData.SessionID != sp.ControllingClient.SessionId) + if (sp != null) { - m_log.WarnFormat( - "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", - sp.UUID, cAgentData.SessionID); + if (cAgentData.SessionID != sp.ControllingClient.SessionId) + { + m_log.WarnFormat( + "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", + sp.UUID, cAgentData.SessionID); - Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}", - sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); - } + Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}", + sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); + } - sp.UpdateChildAgent(cAgentData); + sp.UpdateChildAgent(cAgentData); - int ntimes = 20; - if (cAgentData.SenderWantsToWaitForRoot) - { - while (sp.IsChildAgent && ntimes-- > 0) - Thread.Sleep(1000); + int ntimes = 20; + if (cAgentData.SenderWantsToWaitForRoot) + { + while (sp.IsChildAgent && ntimes-- > 0) + Thread.Sleep(1000); + + if (sp.IsChildAgent) + m_log.WarnFormat( + "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}", + sp.Name, sp.UUID, Name); + else + m_log.InfoFormat( + "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits", + sp.Name, sp.UUID, Name, 20 - ntimes); - if (sp.IsChildAgent) - m_log.WarnFormat( - "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}", - sp.Name, sp.UUID, Name); - else - m_log.InfoFormat( - "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits", - sp.Name, sp.UUID, Name, 20 - ntimes); + if (sp.IsChildAgent) + return false; + } - if (sp.IsChildAgent) - return false; + return true; } - return true; - } - - return false; - } - - /// - /// We've got an update about an agent that sees into this region, - /// send it to ScenePresence for processing It's only positional data - /// - /// AgentPosition that contains agent positional data so we can know what to send - /// true if we handled it. - public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData) - { - // m_log.DebugFormat( - // "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}", - // cAgentData.AgentID, Name, cAgentData.Position); - - ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); - if (childAgentUpdate != null) - { - // if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID) - // // Only warn for now - // m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?", - // childAgentUpdate.UUID, cAgentData.SessionID); - - // I can't imagine *yet* why we would get an update if the agent is a root agent.. - // however to avoid a race condition crossing borders.. - if (childAgentUpdate.IsChildAgent) - { - uint rRegionX = (uint)(cAgentData.RegionHandle >> 40); - uint rRegionY = (((uint)(cAgentData.RegionHandle)) >> 8); - uint tRegionX = RegionInfo.RegionLocX; - uint tRegionY = RegionInfo.RegionLocY; - //Send Data to ScenePresence - childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); - // Not Implemented: - //TODO: Do we need to pass the message on to one of our neighbors? + return false; + } + + /// + /// We've got an update about an agent that sees into this region, + /// send it to ScenePresence for processing It's only positional data + /// + /// AgentPosition that contains agent positional data so we can know what to send + /// true if we handled it. + public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData) + { + // m_log.DebugFormat( + // "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}", + // cAgentData.AgentID, Name, cAgentData.Position); + + ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); + if (childAgentUpdate != null) + { + // if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID) + // // Only warn for now + // m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?", + // childAgentUpdate.UUID, cAgentData.SessionID); + + // I can't imagine *yet* why we would get an update if the agent is a root agent.. + // however to avoid a race condition crossing borders.. + if (childAgentUpdate.IsChildAgent) + { + uint rRegionX = (uint)(cAgentData.RegionHandle >> 40); + uint rRegionY = (((uint)(cAgentData.RegionHandle)) >> 8); + uint tRegionX = RegionInfo.RegionLocX; + uint tRegionY = RegionInfo.RegionLocY; + //Send Data to ScenePresence + childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); + // Not Implemented: + //TODO: Do we need to pass the message on to one of our neighbors? + } + + return true; } - return true; - } - - return false; - } - - /// - /// Poll until the requested ScenePresence appears or we timeout. - /// - /// The scene presence is found, else null. - /// - protected virtual ScenePresence WaitGetScenePresence(UUID agentID) - { - int ntimes = 20; - ScenePresence sp = null; - while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) + return false; + } + + /// + /// Poll until the requested ScenePresence appears or we timeout. + /// + /// The scene presence is found, else null. + /// + protected virtual ScenePresence WaitGetScenePresence(UUID agentID) + { + int ntimes = 20; + ScenePresence sp = null; + while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) Thread.Sleep(1000); - if (sp == null) + if (sp == null) m_log.WarnFormat( - "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", - agentID, RegionInfo.RegionName); - - return sp; - } - - /// - /// Authenticated close (via network) - /// - /// - /// - /// - /// - public bool CloseAgent(UUID agentID, bool force, string auth_token) - { - //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token); - - // Check that the auth_token is valid - AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID); - - if (acd == null) - { - m_log.DebugFormat( - "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.", - agentID, Name); + "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", + agentID, RegionInfo.RegionName); - return false; - } - - if (acd.SessionID.ToString() == auth_token) - { - return CloseAgent(agentID, force); - } - else - { - m_log.WarnFormat( - "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}", - agentID, auth_token, Name); - } + return sp; + } - return false; - } + /// + /// Authenticated close (via network) + /// + /// + /// + /// + /// + public bool CloseAgent(UUID agentID, bool force, string auth_token) + { + //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token); - /// - /// Tell a single client to prepare to close. - /// - /// - /// This should only be called if we may close the client but there will be some delay in so doing. Meant for - /// internal use - other callers should almost certainly called CloseClient(). - /// - /// - /// true if pre-close state notification was successful. false if the agent - /// was not in a state where it could transition to pre-close. - public bool IncomingPreCloseClient(ScenePresence sp) - { - lock (m_removeClientLock) - { - // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may - // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not - // want to obey this close since C may have renewed the child agent lease on B. - if (sp.DoNotCloseAfterTeleport) - { - m_log.DebugFormat( - "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection", - sp.IsChildAgent ? "child" : "root", sp.Name, Name); + // Check that the auth_token is valid + AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID); - // Need to reset the flag so that a subsequent close after another teleport can succeed. - sp.DoNotCloseAfterTeleport = false; + if (acd == null) + { + m_log.DebugFormat( + "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.", + agentID, Name); - return false; + return false; } - if (sp.LifecycleState != ScenePresenceState.Running) + if (acd.SessionID.ToString() == auth_token) { - m_log.DebugFormat( - "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}", - sp.Name, Name, sp.LifecycleState); - - return false; + return CloseAgent(agentID, force); + } + else + { + m_log.WarnFormat( + "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}", + agentID, auth_token, Name); } - sp.LifecycleState = ScenePresenceState.PreRemove; + return false; + } + + /// + /// Tell a single client to prepare to close. + /// + /// + /// This should only be called if we may close the client but there will be some delay in so doing. Meant for + /// internal use - other callers should almost certainly called CloseClient(). + /// + /// + /// true if pre-close state notification was successful. false if the agent + /// was not in a state where it could transition to pre-close. + public bool IncomingPreCloseClient(ScenePresence sp) + { + lock (m_removeClientLock) + { + // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may + // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not + // want to obey this close since C may have renewed the child agent lease on B. + if (sp.DoNotCloseAfterTeleport) + { + m_log.DebugFormat( + "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection", + sp.IsChildAgent ? "child" : "root", sp.Name, Name); + + // Need to reset the flag so that a subsequent close after another teleport can succeed. + sp.DoNotCloseAfterTeleport = false; + + return false; + } + + if (sp.LifecycleState != ScenePresenceState.Running) + { + m_log.DebugFormat( + "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}", + sp.Name, Name, sp.LifecycleState); + + return false; + } + + sp.LifecycleState = ScenePresenceState.PreRemove; + + return true; + } + } + + /// + /// Tell a single agent to disconnect from the region. + /// + /// + /// + /// Force the agent to close even if it might be in the middle of some other operation. You do not want to + /// force unless you are absolutely sure that the agent is dead and a normal close is not working. + /// + public override bool CloseAgent(UUID agentID, bool force) + { + ScenePresence sp; + + lock (m_removeClientLock) + { + sp = GetScenePresence(agentID); + + if (sp == null) + { + m_log.DebugFormat( + "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", + agentID, Name); + + return false; + } + + if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove) + { + m_log.DebugFormat( + "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}", + sp.Name, Name, sp.LifecycleState); + + return false; + } + + // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may + // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not + // want to obey this close since C may have renewed the child agent lease on B. + if (sp.DoNotCloseAfterTeleport) + { + m_log.DebugFormat( + "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection", + sp.IsChildAgent ? "child" : "root", sp.Name, Name); + + // Need to reset the flag so that a subsequent close after another teleport can succeed. + sp.DoNotCloseAfterTeleport = false; + + return false; + } + + sp.LifecycleState = ScenePresenceState.Removing; + } + + sp.ControllingClient.Close(force); return true; - } - } - - /// - /// Tell a single agent to disconnect from the region. - /// - /// - /// - /// Force the agent to close even if it might be in the middle of some other operation. You do not want to - /// force unless you are absolutely sure that the agent is dead and a normal close is not working. - /// - public override bool CloseAgent(UUID agentID, bool force) - { - ScenePresence sp; - - lock (m_removeClientLock) - { - sp = GetScenePresence(agentID); - - if (sp == null) + } + + /// + /// Tries to teleport agent to another region. + /// + /// + /// The region name must exactly match that given. + /// + /// + /// + /// + /// + /// + public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, + Vector3 lookat, uint teleportFlags) + { + GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName); + + if (region == null) + { + // can't find the region: Tell viewer and abort + remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); + return; + } + + RequestTeleportLocation(remoteClient, region.RegionHandle, position, lookat, teleportFlags); + } + + /// + /// Tries to teleport agent to other region. + /// + /// + /// + /// + /// + /// + public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, + Vector3 lookAt, uint teleportFlags) + { + ScenePresence sp = GetScenePresence(remoteClient.AgentId); + if (sp != null) { - m_log.DebugFormat( - "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", - agentID, Name); - - return false; + if (EntityTransferModule != null) + { + EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); + } + else + { + m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active"); + sp.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator."); + } } + } - if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove) + public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) + { + if (EntityTransferModule != null) { - m_log.DebugFormat( - "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}", - sp.Name, Name, sp.LifecycleState); - - return false; + return EntityTransferModule.Cross(agent, isFlying); } - - // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may - // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not - // want to obey this close since C may have renewed the child agent lease on B. - if (sp.DoNotCloseAfterTeleport) + else { - m_log.DebugFormat( - "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection", - sp.IsChildAgent ? "child" : "root", sp.Name, Name); - - // Need to reset the flag so that a subsequent close after another teleport can succeed. - sp.DoNotCloseAfterTeleport = false; - - return false; + m_log.DebugFormat("[SCENE]: Unable to cross agent to neighbouring region, because there is no AgentTransferModule"); } - sp.LifecycleState = ScenePresenceState.Removing; - } - - sp.ControllingClient.Close(force); - - return true; - } - - /// - /// Tries to teleport agent to another region. - /// - /// - /// The region name must exactly match that given. - /// - /// - /// - /// - /// - /// - public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, - Vector3 lookat, uint teleportFlags) - { - GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName); + return false; + } + + public void SendOutChildAgentUpdates(AgentPosition cadu, ScenePresence presence) + { + m_sceneGridService.SendChildAgentDataUpdate(cadu, presence); + } + + #endregion + + #region Other Methods + + protected override IConfigSource GetConfig() + { + return m_config; + } + + #endregion + + public void HandleObjectPermissionsUpdate(IClientAPI controller, UUID agentID, UUID sessionID, byte field, uint localId, uint mask, byte set) + { + // Check for spoofing.. since this is permissions we're talking about here! + if ((controller.SessionId == sessionID) && (controller.AgentId == agentID)) + { + // Tell the object to do permission update + if (localId != 0) + { + SceneObjectGroup chObjectGroup = GetGroupByPrim(localId); + if (chObjectGroup != null) + { + chObjectGroup.UpdatePermissions(agentID, field, localId, mask, set); + } + } + } + } + + /// + /// Causes all clients to get a full object update on all of the objects in the scene. + /// + public void ForceClientUpdate() + { + EntityBase[] entityList = GetEntities(); + foreach (EntityBase ent in entityList) + { + if (ent is SceneObjectGroup) + { + ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); + } + } + } + + /// + /// This is currently only used for scale (to scale to MegaPrim size) + /// There is a console command that calls this in OpenSimMain + /// + /// + public void HandleEditCommand(string[] cmdparams) + { + m_log.DebugFormat("Searching for Primitive: '{0}'", cmdparams[2]); + + EntityBase[] entityList = GetEntities(); + foreach (EntityBase ent in entityList) + { + if (ent is SceneObjectGroup) + { + SceneObjectPart part = ((SceneObjectGroup)ent).GetPart(((SceneObjectGroup)ent).UUID); + if (part != null) + { + if (part.Name == cmdparams[2]) + { + part.Resize( + new Vector3(Convert.ToSingle(cmdparams[3]), Convert.ToSingle(cmdparams[4]), + Convert.ToSingle(cmdparams[5]))); + + m_log.DebugFormat("Edited scale of Primitive: {0}", part.Name); + } + } + } + } + } + + #region Script Handling Methods + + /// + /// Console command handler to send script command to script engine. + /// + /// + public void SendCommandToPlugins(string[] args) + { + m_eventManager.TriggerOnPluginConsole(args); + } + + public LandData GetLandData(float x, float y) + { + return LandChannel.GetLandObject(x, y).LandData; + } + + /// + /// Get LandData by position. + /// + /// + /// + public LandData GetLandData(Vector3 pos) + { + return GetLandData(pos.X, pos.Y); + } + + public LandData GetLandData(uint x, uint y) + { + m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); + return LandChannel.GetLandObject((int)x, (int)y).LandData; + } + + #endregion + + #region Script Engine + + private bool ScriptDanger(SceneObjectPart part, Vector3 pos) + { + ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); + if (part != null) + { + if (parcel != null) + { + if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0) + { + return true; + } + else if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID)) + { + return true; + } + else if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0) + && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID)) + { + return true; + } + else + { + return false; + } + } + else + { + + if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY) + { + // The only time parcel != null when an object is inside a region is when + // there is nothing behind the landchannel. IE, no land plugin loaded. + return true; + } + else + { + // The object is outside of this region. Stop piping events to it. + return false; + } + } + } + else + { + return false; + } + } - if (region == null) - { - // can't find the region: Tell viewer and abort - remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); - return; - } - - RequestTeleportLocation(remoteClient, region.RegionHandle, position, lookat, teleportFlags); - } - - /// - /// Tries to teleport agent to other region. - /// - /// - /// - /// - /// - /// - public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, - Vector3 lookAt, uint teleportFlags) - { - ScenePresence sp = GetScenePresence(remoteClient.AgentId); - if (sp != null) - { - if (EntityTransferModule != null) + public bool ScriptDanger(uint localID, Vector3 pos) + { + SceneObjectPart part = GetSceneObjectPart(localID); + if (part != null) { - EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); + return ScriptDanger(part, pos); } else { - m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active"); - sp.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator."); - } - } - } - - public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) - { - if (EntityTransferModule != null) - { - return EntityTransferModule.Cross(agent, isFlying); - } - else - { - m_log.DebugFormat("[SCENE]: Unable to cross agent to neighbouring region, because there is no AgentTransferModule"); - } - - return false; - } - - public void SendOutChildAgentUpdates(AgentPosition cadu, ScenePresence presence) - { - m_sceneGridService.SendChildAgentDataUpdate(cadu, presence); - } - - #endregion - - #region Other Methods - - protected override IConfigSource GetConfig() - { - return m_config; - } - - #endregion - - public void HandleObjectPermissionsUpdate(IClientAPI controller, UUID agentID, UUID sessionID, byte field, uint localId, uint mask, byte set) - { - // Check for spoofing.. since this is permissions we're talking about here! - if ((controller.SessionId == sessionID) && (controller.AgentId == agentID)) - { - // Tell the object to do permission update - if (localId != 0) - { - SceneObjectGroup chObjectGroup = GetGroupByPrim(localId); - if (chObjectGroup != null) - { - chObjectGroup.UpdatePermissions(agentID, field, localId, mask, set); - } - } - } - } - - /// - /// Causes all clients to get a full object update on all of the objects in the scene. - /// - public void ForceClientUpdate() - { - EntityBase[] entityList = GetEntities(); - foreach (EntityBase ent in entityList) - { - if (ent is SceneObjectGroup) - { - ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); - } - } - } - - /// - /// This is currently only used for scale (to scale to MegaPrim size) - /// There is a console command that calls this in OpenSimMain - /// - /// - public void HandleEditCommand(string[] cmdparams) - { - m_log.DebugFormat("Searching for Primitive: '{0}'", cmdparams[2]); - - EntityBase[] entityList = GetEntities(); - foreach (EntityBase ent in entityList) - { - if (ent is SceneObjectGroup) - { - SceneObjectPart part = ((SceneObjectGroup)ent).GetPart(((SceneObjectGroup)ent).UUID); - if (part != null) - { - if (part.Name == cmdparams[2]) - { - part.Resize( - new Vector3(Convert.ToSingle(cmdparams[3]), Convert.ToSingle(cmdparams[4]), - Convert.ToSingle(cmdparams[5]))); - - m_log.DebugFormat("Edited scale of Primitive: {0}", part.Name); - } - } - } - } - } - - #region Script Handling Methods - - /// - /// Console command handler to send script command to script engine. - /// - /// - public void SendCommandToPlugins(string[] args) - { - m_eventManager.TriggerOnPluginConsole(args); - } - - public LandData GetLandData(float x, float y) - { - return LandChannel.GetLandObject(x, y).LandData; - } - - /// - /// Get LandData by position. - /// - /// - /// - public LandData GetLandData(Vector3 pos) - { - return GetLandData(pos.X, pos.Y); - } - - public LandData GetLandData(uint x, uint y) - { - m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); - return LandChannel.GetLandObject((int)x, (int)y).LandData; - } - - #endregion - - #region Script Engine - - private bool ScriptDanger(SceneObjectPart part, Vector3 pos) - { - ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); - if (part != null) - { - if (parcel != null) - { - if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0) - { - return true; - } - else if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID)) - { - return true; - } - else if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0) - && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID)) - { - return true; - } - else - { - return false; - } + return false; + } + } + + public bool PipeEventsForScript(uint localID) + { + SceneObjectPart part = GetSceneObjectPart(localID); + + if (part != null) + { + SceneObjectPart parent = part.ParentGroup.RootPart; + return ScriptDanger(parent, parent.GetWorldPosition()); } else { + return false; + } + } + + #endregion + + #region SceneGraph wrapper methods + + /// + /// + /// + /// + /// + public UUID ConvertLocalIDToFullID(uint localID) + { + return m_sceneGraph.ConvertLocalIDToFullID(localID); + } + + public void SwapRootAgentCount(bool rootChildChildRootTF) + { + m_sceneGraph.SwapRootChildAgent(rootChildChildRootTF); + } + + public void AddPhysicalPrim(int num) + { + m_sceneGraph.AddPhysicalPrim(num); + } + + public void RemovePhysicalPrim(int num) + { + m_sceneGraph.RemovePhysicalPrim(num); + } + + public int GetRootAgentCount() + { + return m_sceneGraph.GetRootAgentCount(); + } + + public int GetChildAgentCount() + { + return m_sceneGraph.GetChildAgentCount(); + } + + /// + /// Request a scene presence by UUID. Fast, indexed lookup. + /// + /// + /// null if the presence was not found + public ScenePresence GetScenePresence(UUID agentID) + { + return m_sceneGraph.GetScenePresence(agentID); + } + + /// + /// Request the scene presence by name. + /// + /// + /// + /// null if the presence was not found + public ScenePresence GetScenePresence(string firstName, string lastName) + { + return m_sceneGraph.GetScenePresence(firstName, lastName); + } + + /// + /// Request the scene presence by localID. + /// + /// + /// null if the presence was not found + public ScenePresence GetScenePresence(uint localID) + { + return m_sceneGraph.GetScenePresence(localID); + } + + /// + /// Gets all the scene presences in this scene. + /// + /// + /// This method will return both root and child scene presences. + /// + /// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not + /// involving creating a new List object. + /// + /// + /// A list of the scene presences. Adding or removing from the list will not affect the presences in the scene. + /// + public List GetScenePresences() + { + return new List(m_sceneGraph.GetScenePresences()); + } + + /// + /// Performs action on all avatars in the scene (root scene presences) + /// Avatars may be an NPC or a 'real' client. + /// + /// + public void ForEachRootScenePresence(Action action) + { + m_sceneGraph.ForEachAvatar(action); + } + + /// + /// Performs action on all scene presences (root and child) + /// + /// + public void ForEachScenePresence(Action action) + { + m_sceneGraph.ForEachScenePresence(action); + } + + /// + /// Get all the scene object groups. + /// + /// + /// The scene object groups. If the scene is empty then an empty list is returned. + /// + public List GetSceneObjectGroups() + { + return m_sceneGraph.GetSceneObjectGroups(); + } + + /// + /// Get a group via its UUID + /// + /// + /// null if no group with that id exists + public SceneObjectGroup GetSceneObjectGroup(UUID fullID) + { + return m_sceneGraph.GetSceneObjectGroup(fullID); + } + + /// + /// Get a group via its local ID + /// + /// This will only return a group if the local ID matches a root part + /// + /// null if no group with that id exists + public SceneObjectGroup GetSceneObjectGroup(uint localID) + { + return m_sceneGraph.GetSceneObjectGroup(localID); + } + + /// + /// Get a group by name from the scene (will return the first + /// found, if there are more than one prim with the same name) + /// + /// + /// null if no group with that name exists + public SceneObjectGroup GetSceneObjectGroup(string name) + { + return m_sceneGraph.GetSceneObjectGroup(name); + } + + /// + /// Attempt to get the SOG via its UUID + /// + /// + /// + /// + public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog) + { + sog = GetSceneObjectGroup(fullID); + return sog != null; + } + + /// + /// Get a prim by name from the scene (will return the first + /// found, if there are more than one prim with the same name) + /// + /// + /// + public SceneObjectPart GetSceneObjectPart(string name) + { + return m_sceneGraph.GetSceneObjectPart(name); + } + + /// + /// Get a prim via its local id + /// + /// + /// + public SceneObjectPart GetSceneObjectPart(uint localID) + { + return m_sceneGraph.GetSceneObjectPart(localID); + } + + /// + /// Get a prim via its UUID + /// + /// + /// + public SceneObjectPart GetSceneObjectPart(UUID fullID) + { + return m_sceneGraph.GetSceneObjectPart(fullID); + } + + /// + /// Attempt to get a prim via its UUID + /// + /// + /// + /// + public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop) + { + sop = GetSceneObjectPart(fullID); + return sop != null; + } + + /// + /// Get a scene object group that contains the prim with the given local id + /// + /// + /// null if no scene object group containing that prim is found + public SceneObjectGroup GetGroupByPrim(uint localID) + { + return m_sceneGraph.GetGroupByPrim(localID); + } + + /// + /// Get a scene object group that contains the prim with the given uuid + /// + /// + /// null if no scene object group containing that prim is found + public SceneObjectGroup GetGroupByPrim(UUID fullID) + { + return m_sceneGraph.GetGroupByPrim(fullID); + } + + public override bool TryGetScenePresence(UUID agentID, out ScenePresence sp) + { + return m_sceneGraph.TryGetScenePresence(agentID, out sp); + } + + public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) + { + return m_sceneGraph.TryGetAvatarByName(avatarName, out avatar); + } + + /// + /// Perform an action on all clients with an avatar in this scene (root only) + /// + /// + public void ForEachRootClient(Action action) + { + ForEachRootScenePresence(delegate(ScenePresence presence) + { + action(presence.ControllingClient); + }); + } + + /// + /// Perform an action on all clients connected to the region (root and child) + /// + /// + public void ForEachClient(Action action) + { + m_clientManager.ForEachSync(action); + } + + public bool TryGetClient(UUID avatarID, out IClientAPI client) + { + return m_clientManager.TryGetValue(avatarID, out client); + } + + public bool TryGetClient(System.Net.IPEndPoint remoteEndPoint, out IClientAPI client) + { + return m_clientManager.TryGetValue(remoteEndPoint, out client); + } + + public void ForEachSOG(Action action) + { + m_sceneGraph.ForEachSOG(action); + } + + /// + /// Returns a list of the entities in the scene. This is a new list so operations perform on the list itself + /// will not affect the original list of objects in the scene. + /// + /// + public EntityBase[] GetEntities() + { + return m_sceneGraph.GetEntities(); + } + + #endregion + + + // Commented pending deletion since this method no longer appears to do anything at all + // public bool NeedSceneCacheClear(UUID agentID) + // { + // IInventoryTransferModule inv = RequestModuleInterface(); + // if (inv == null) + // return true; + // + // return inv.NeedSceneCacheClear(agentID, this); + // } + + public void CleanTempObjects() + { + EntityBase[] entities = GetEntities(); + foreach (EntityBase obj in entities) + { + if (obj is SceneObjectGroup) + { + SceneObjectGroup grp = (SceneObjectGroup)obj; + + if (!grp.IsDeleted) + { + if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) + { + if (grp.RootPart.Expires <= DateTime.Now) + DeleteSceneObject(grp, false); + } + } + } + } + + } + + public void DeleteFromStorage(UUID uuid) + { + SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); + } + + public int GetHealth() + { + // Returns: + // 1 = sim is up and accepting http requests. The heartbeat has + // stopped and the sim is probably locked up, but a remote + // admin restart may succeed + // + // 2 = Sim is up and the heartbeat is running. The sim is likely + // usable for people within and logins _may_ work + // + // 3 = We have seen a new user enter within the past 4 minutes + // which can be seen as positive confirmation of sim health + // + int health = 1; // Start at 1, means we're up - if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY) - { - // The only time parcel != null when an object is inside a region is when - // there is nothing behind the landchannel. IE, no land plugin loaded. - return true; - } - else - { - // The object is outside of this region. Stop piping events to it. - return false; - } - } - } - else - { - return false; - } - } - - public bool ScriptDanger(uint localID, Vector3 pos) - { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null) - { - return ScriptDanger(part, pos); - } - else - { - return false; - } - } - - public bool PipeEventsForScript(uint localID) - { - SceneObjectPart part = GetSceneObjectPart(localID); - - if (part != null) - { - SceneObjectPart parent = part.ParentGroup.RootPart; - return ScriptDanger(parent, parent.GetWorldPosition()); - } - else - { - return false; - } - } - - #endregion - - #region SceneGraph wrapper methods - - /// - /// - /// - /// - /// - public UUID ConvertLocalIDToFullID(uint localID) - { - return m_sceneGraph.ConvertLocalIDToFullID(localID); - } - - public void SwapRootAgentCount(bool rootChildChildRootTF) - { - m_sceneGraph.SwapRootChildAgent(rootChildChildRootTF); - } - - public void AddPhysicalPrim(int num) - { - m_sceneGraph.AddPhysicalPrim(num); - } - - public void RemovePhysicalPrim(int num) - { - m_sceneGraph.RemovePhysicalPrim(num); - } - - public int GetRootAgentCount() - { - return m_sceneGraph.GetRootAgentCount(); - } - - public int GetChildAgentCount() - { - return m_sceneGraph.GetChildAgentCount(); - } - - /// - /// Request a scene presence by UUID. Fast, indexed lookup. - /// - /// - /// null if the presence was not found - public ScenePresence GetScenePresence(UUID agentID) - { - return m_sceneGraph.GetScenePresence(agentID); - } - - /// - /// Request the scene presence by name. - /// - /// - /// - /// null if the presence was not found - public ScenePresence GetScenePresence(string firstName, string lastName) - { - return m_sceneGraph.GetScenePresence(firstName, lastName); - } - - /// - /// Request the scene presence by localID. - /// - /// - /// null if the presence was not found - public ScenePresence GetScenePresence(uint localID) - { - return m_sceneGraph.GetScenePresence(localID); - } - - /// - /// Gets all the scene presences in this scene. - /// - /// - /// This method will return both root and child scene presences. - /// - /// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not - /// involving creating a new List object. - /// - /// - /// A list of the scene presences. Adding or removing from the list will not affect the presences in the scene. - /// - public List GetScenePresences() - { - return new List(m_sceneGraph.GetScenePresences()); - } - - /// - /// Performs action on all avatars in the scene (root scene presences) - /// Avatars may be an NPC or a 'real' client. - /// - /// - public void ForEachRootScenePresence(Action action) - { - m_sceneGraph.ForEachAvatar(action); - } - - /// - /// Performs action on all scene presences (root and child) - /// - /// - public void ForEachScenePresence(Action action) - { - m_sceneGraph.ForEachScenePresence(action); - } - - /// - /// Get all the scene object groups. - /// - /// - /// The scene object groups. If the scene is empty then an empty list is returned. - /// - public List GetSceneObjectGroups() - { - return m_sceneGraph.GetSceneObjectGroups(); - } - - /// - /// Get a group via its UUID - /// - /// - /// null if no group with that id exists - public SceneObjectGroup GetSceneObjectGroup(UUID fullID) - { - return m_sceneGraph.GetSceneObjectGroup(fullID); - } - - /// - /// Get a group via its local ID - /// - /// This will only return a group if the local ID matches a root part - /// - /// null if no group with that id exists - public SceneObjectGroup GetSceneObjectGroup(uint localID) - { - return m_sceneGraph.GetSceneObjectGroup(localID); - } - - /// - /// Get a group by name from the scene (will return the first - /// found, if there are more than one prim with the same name) - /// - /// - /// null if no group with that name exists - public SceneObjectGroup GetSceneObjectGroup(string name) - { - return m_sceneGraph.GetSceneObjectGroup(name); - } - - /// - /// Attempt to get the SOG via its UUID - /// - /// - /// - /// - public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog) - { - sog = GetSceneObjectGroup(fullID); - return sog != null; - } - - /// - /// Get a prim by name from the scene (will return the first - /// found, if there are more than one prim with the same name) - /// - /// - /// - public SceneObjectPart GetSceneObjectPart(string name) - { - return m_sceneGraph.GetSceneObjectPart(name); - } - - /// - /// Get a prim via its local id - /// - /// - /// - public SceneObjectPart GetSceneObjectPart(uint localID) - { - return m_sceneGraph.GetSceneObjectPart(localID); - } - - /// - /// Get a prim via its UUID - /// - /// - /// - public SceneObjectPart GetSceneObjectPart(UUID fullID) - { - return m_sceneGraph.GetSceneObjectPart(fullID); - } - - /// - /// Attempt to get a prim via its UUID - /// - /// - /// - /// - public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop) - { - sop = GetSceneObjectPart(fullID); - return sop != null; - } - - /// - /// Get a scene object group that contains the prim with the given local id - /// - /// - /// null if no scene object group containing that prim is found - public SceneObjectGroup GetGroupByPrim(uint localID) - { - return m_sceneGraph.GetGroupByPrim(localID); - } - - /// - /// Get a scene object group that contains the prim with the given uuid - /// - /// - /// null if no scene object group containing that prim is found - public SceneObjectGroup GetGroupByPrim(UUID fullID) - { - return m_sceneGraph.GetGroupByPrim(fullID); - } - - public override bool TryGetScenePresence(UUID agentID, out ScenePresence sp) - { - return m_sceneGraph.TryGetScenePresence(agentID, out sp); - } - - public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) - { - return m_sceneGraph.TryGetAvatarByName(avatarName, out avatar); - } - - /// - /// Perform an action on all clients with an avatar in this scene (root only) - /// - /// - public void ForEachRootClient(Action action) - { - ForEachRootScenePresence(delegate(ScenePresence presence) - { - action(presence.ControllingClient); - }); - } - - /// - /// Perform an action on all clients connected to the region (root and child) - /// - /// - public void ForEachClient(Action action) - { - m_clientManager.ForEachSync(action); - } - - public bool TryGetClient(UUID avatarID, out IClientAPI client) - { - return m_clientManager.TryGetValue(avatarID, out client); - } - - public bool TryGetClient(System.Net.IPEndPoint remoteEndPoint, out IClientAPI client) - { - return m_clientManager.TryGetValue(remoteEndPoint, out client); - } - - public void ForEachSOG(Action action) - { - m_sceneGraph.ForEachSOG(action); - } - - /// - /// Returns a list of the entities in the scene. This is a new list so operations perform on the list itself - /// will not affect the original list of objects in the scene. - /// - /// - public EntityBase[] GetEntities() - { - return m_sceneGraph.GetEntities(); - } - - #endregion - - - // Commented pending deletion since this method no longer appears to do anything at all - // public bool NeedSceneCacheClear(UUID agentID) - // { - // IInventoryTransferModule inv = RequestModuleInterface(); - // if (inv == null) - // return true; - // - // return inv.NeedSceneCacheClear(agentID, this); - // } - - public void CleanTempObjects() - { - EntityBase[] entities = GetEntities(); - foreach (EntityBase obj in entities) - { - if (obj is SceneObjectGroup) - { - SceneObjectGroup grp = (SceneObjectGroup)obj; - - if (!grp.IsDeleted) - { - if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) - { - if (grp.RootPart.Expires <= DateTime.Now) - DeleteSceneObject(grp, false); - } - } - } - } - - } - - public void DeleteFromStorage(UUID uuid) - { - SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); - } - - public int GetHealth() - { - // Returns: - // 1 = sim is up and accepting http requests. The heartbeat has - // stopped and the sim is probably locked up, but a remote - // admin restart may succeed - // - // 2 = Sim is up and the heartbeat is running. The sim is likely - // usable for people within and logins _may_ work - // - // 3 = We have seen a new user enter within the past 4 minutes - // which can be seen as positive confirmation of sim health - // - int health = 1; // Start at 1, means we're up - - if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) + if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) health += 1; - else + else return health; - // A login in the last 4 mins? We can't be doing too badly - // - if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) + // A login in the last 4 mins? We can't be doing too badly + // + if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) health++; - else + else return health; - // CheckHeartbeat(); - - return health; - } + // CheckHeartbeat(); - // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and - // update non-physical objects like the joint proxy objects that represent the position - // of the joints in the scene. + return health; + } - // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene - // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called - // from within the OdePhysicsScene. + // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and + // update non-physical objects like the joint proxy objects that represent the position + // of the joints in the scene. - protected internal void jointMoved(PhysicsJoint joint) - { - // m_parentScene.PhysicsScene.DumpJointInfo(); // non-thread-locked version; we should already be in a lock (OdeLock) when this callback is invoked - SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); - if (jointProxyObject == null) - { - jointErrorMessage(joint, "WARNING, joint proxy not found, name " + joint.ObjectNameInScene); - return; - } - - // now update the joint proxy object in the scene to have the position of the joint as returned by the physics engine - SceneObjectPart trackedBody = GetSceneObjectPart(joint.TrackedBodyName); // FIXME: causes a sequential lookup - if (trackedBody == null) return; // the actor may have been deleted but the joint still lingers around a few frames waiting for deletion. during this time, trackedBody is NULL to prevent further motion of the joint proxy. - jointProxyObject.Velocity = trackedBody.Velocity; - jointProxyObject.AngularVelocity = trackedBody.AngularVelocity; - switch (joint.Type) - { - case PhysicsJointType.Ball: - { - Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); - Vector3 proxyPos = jointAnchor; - jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update - } - break; - - case PhysicsJointType.Hinge: - { - Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); - - // Normally, we would just ask the physics scene to return the axis for the joint. - // Unfortunately, ODE sometimes returns <0,0,0> for the joint axis, which should - // never occur. Therefore we cannot rely on ODE to always return a correct joint axis. - // Therefore the following call does not always work: - //PhysicsVector phyJointAxis = _PhyScene.GetJointAxis(joint); - - // instead we compute the joint orientation by saving the original joint orientation - // relative to one of the jointed bodies, and applying this transformation - // to the current position of the jointed bodies (the tracked body) to compute the - // current joint orientation. - - if (joint.TrackedBodyName == null) - { - jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene); - } - - Vector3 proxyPos = jointAnchor; - Quaternion q = trackedBody.RotationOffset * joint.LocalRotation; - - jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update - jointProxyObject.ParentGroup.UpdateGroupRotationR(q); // schedules the entire group for a terse update - } - break; - } - } - - // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and - // update non-physical objects like the joint proxy objects that represent the position - // of the joints in the scene. - - // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene - // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called - // from within the OdePhysicsScene. - protected internal void jointDeactivated(PhysicsJoint joint) - { - //m_log.Debug("[NINJA] SceneGraph.jointDeactivated, joint:" + joint.ObjectNameInScene); - SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); - if (jointProxyObject == null) - { - jointErrorMessage(joint, "WARNING, trying to deactivate (stop interpolation of) joint proxy, but not found, name " + joint.ObjectNameInScene); - return; - } - - // turn the proxy non-physical, which also stops its client-side interpolation - bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); - if (wasUsingPhysics) - { - jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock - } - } - - // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and - // alert the user of errors by using the debug channel in the same way that scripts alert - // the user of compile errors. - - // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene - // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called - // from within the OdePhysicsScene. - public void jointErrorMessage(PhysicsJoint joint, string message) - { - if (joint != null) - { - if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages) - return; + // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene + // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called + // from within the OdePhysicsScene. + protected internal void jointMoved(PhysicsJoint joint) + { + // m_parentScene.PhysicsScene.DumpJointInfo(); // non-thread-locked version; we should already be in a lock (OdeLock) when this callback is invoked SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); - if (jointProxyObject != null) - { - SimChat(Utils.StringToBytes("[NINJA]: " + message), - ChatTypeEnum.DebugChannel, - 2147483647, - jointProxyObject.AbsolutePosition, - jointProxyObject.Name, - jointProxyObject.UUID, - false); - - joint.ErrorMessageCount++; - - if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages) - { - SimChat(Utils.StringToBytes("[NINJA]: Too many messages for this joint, suppressing further messages."), - ChatTypeEnum.DebugChannel, - 2147483647, - jointProxyObject.AbsolutePosition, - jointProxyObject.Name, - jointProxyObject.UUID, - false); - } - } - else + if (jointProxyObject == null) { - // couldn't find the joint proxy object; the error message is silently suppressed + jointErrorMessage(joint, "WARNING, joint proxy not found, name " + joint.ObjectNameInScene); + return; } - } - } - public Scene ConsoleScene() - { - if (MainConsole.Instance == null) + // now update the joint proxy object in the scene to have the position of the joint as returned by the physics engine + SceneObjectPart trackedBody = GetSceneObjectPart(joint.TrackedBodyName); // FIXME: causes a sequential lookup + if (trackedBody == null) return; // the actor may have been deleted but the joint still lingers around a few frames waiting for deletion. during this time, trackedBody is NULL to prevent further motion of the joint proxy. + jointProxyObject.Velocity = trackedBody.Velocity; + jointProxyObject.AngularVelocity = trackedBody.AngularVelocity; + switch (joint.Type) + { + case PhysicsJointType.Ball: + { + Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); + Vector3 proxyPos = jointAnchor; + jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update + } + break; + + case PhysicsJointType.Hinge: + { + Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); + + // Normally, we would just ask the physics scene to return the axis for the joint. + // Unfortunately, ODE sometimes returns <0,0,0> for the joint axis, which should + // never occur. Therefore we cannot rely on ODE to always return a correct joint axis. + // Therefore the following call does not always work: + //PhysicsVector phyJointAxis = _PhyScene.GetJointAxis(joint); + + // instead we compute the joint orientation by saving the original joint orientation + // relative to one of the jointed bodies, and applying this transformation + // to the current position of the jointed bodies (the tracked body) to compute the + // current joint orientation. + + if (joint.TrackedBodyName == null) + { + jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene); + } + + Vector3 proxyPos = jointAnchor; + Quaternion q = trackedBody.RotationOffset * joint.LocalRotation; + + jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update + jointProxyObject.ParentGroup.UpdateGroupRotationR(q); // schedules the entire group for a terse update + } + break; + } + } + + // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and + // update non-physical objects like the joint proxy objects that represent the position + // of the joints in the scene. + + // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene + // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called + // from within the OdePhysicsScene. + protected internal void jointDeactivated(PhysicsJoint joint) + { + //m_log.Debug("[NINJA] SceneGraph.jointDeactivated, joint:" + joint.ObjectNameInScene); + SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); + if (jointProxyObject == null) + { + jointErrorMessage(joint, "WARNING, trying to deactivate (stop interpolation of) joint proxy, but not found, name " + joint.ObjectNameInScene); + return; + } + + // turn the proxy non-physical, which also stops its client-side interpolation + bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); + if (wasUsingPhysics) + { + jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock + } + } + + // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and + // alert the user of errors by using the debug channel in the same way that scripts alert + // the user of compile errors. + + // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene + // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called + // from within the OdePhysicsScene. + public void jointErrorMessage(PhysicsJoint joint, string message) + { + if (joint != null) + { + if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages) + return; + + SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); + if (jointProxyObject != null) + { + SimChat(Utils.StringToBytes("[NINJA]: " + message), + ChatTypeEnum.DebugChannel, + 2147483647, + jointProxyObject.AbsolutePosition, + jointProxyObject.Name, + jointProxyObject.UUID, + false); + + joint.ErrorMessageCount++; + + if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages) + { + SimChat(Utils.StringToBytes("[NINJA]: Too many messages for this joint, suppressing further messages."), + ChatTypeEnum.DebugChannel, + 2147483647, + jointProxyObject.AbsolutePosition, + jointProxyObject.Name, + jointProxyObject.UUID, + false); + } + } + else + { + // couldn't find the joint proxy object; the error message is silently suppressed + } + } + } + + public Scene ConsoleScene() + { + if (MainConsole.Instance == null) return null; - if (MainConsole.Instance.ConsoleScene is Scene) + if (MainConsole.Instance.ConsoleScene is Scene) return (Scene)MainConsole.Instance.ConsoleScene; - return null; - } - - // Get terrain height at the specified location. - // Presumes the underlying implementation is a heightmap which is a 1m grid. - // Finds heightmap grid points before and after the point and - // does a linear approximation of the height at this intermediate point. - public float GetGroundHeight(float x, float y) - { - if (x < 0) + return null; + } + + // Get terrain height at the specified location. + // Presumes the underlying implementation is a heightmap which is a 1m grid. + // Finds heightmap grid points before and after the point and + // does a linear approximation of the height at this intermediate point. + public float GetGroundHeight(float x, float y) + { + if (x < 0) x = 0; - if (x >= Heightmap.Width) + if (x >= Heightmap.Width) x = Heightmap.Width - 1; - if (y < 0) + if (y < 0) y = 0; - if (y >= Heightmap.Height) + if (y >= Heightmap.Height) y = Heightmap.Height - 1; - Vector3 p0 = new Vector3(x, y, (float)Heightmap[(int)x, (int)y]); - Vector3 p1 = p0; - Vector3 p2 = p0; + Vector3 p0 = new Vector3(x, y, (float)Heightmap[(int)x, (int)y]); + Vector3 p1 = p0; + Vector3 p2 = p0; - p1.X += 1.0f; - if (p1.X < Heightmap.Width) + p1.X += 1.0f; + if (p1.X < Heightmap.Width) p1.Z = (float)Heightmap[(int)p1.X, (int)p1.Y]; - p2.Y += 1.0f; - if (p2.Y < Heightmap.Height) + p2.Y += 1.0f; + if (p2.Y < Heightmap.Height) p2.Z = (float)Heightmap[(int)p2.X, (int)p2.Y]; - Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); - Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z); + Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); + Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z); - v0.Normalize(); - v1.Normalize(); + v0.Normalize(); + v1.Normalize(); - Vector3 vsn = new Vector3(); - vsn.X = (v0.Y * v1.Z) - (v0.Z * v1.Y); - vsn.Y = (v0.Z * v1.X) - (v0.X * v1.Z); - vsn.Z = (v0.X * v1.Y) - (v0.Y * v1.X); - vsn.Normalize(); + Vector3 vsn = new Vector3(); + vsn.X = (v0.Y * v1.Z) - (v0.Z * v1.Y); + vsn.Y = (v0.Z * v1.X) - (v0.X * v1.Z); + vsn.Z = (v0.X * v1.Y) - (v0.Y * v1.X); + vsn.Normalize(); - float xdiff = x - (float)((int)x); - float ydiff = y - (float)((int)y); + float xdiff = x - (float)((int)x); + float ydiff = y - (float)((int)y); - return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; - } + return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; + } - // private void CheckHeartbeat() - // { - // if (m_firstHeartbeat) - // return; - // - // if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) - // StartTimer(); - // } - - public override ISceneObject DeserializeObject(string representation) - { - return SceneObjectSerializer.FromXml2Format(representation); - } + // private void CheckHeartbeat() + // { + // if (m_firstHeartbeat) + // return; + // + // if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) + // StartTimer(); + // } - public override bool AllowScriptCrossings - { - get { return m_allowScriptCrossings; } - } + public override ISceneObject DeserializeObject(string representation) + { + return SceneObjectSerializer.FromXml2Format(representation); + } - public Vector3 GetNearestAllowedPosition(ScenePresence avatar) - { - return GetNearestAllowedPosition(avatar, null); - } + public override bool AllowScriptCrossings + { + get { return m_allowScriptCrossings; } + } - public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel) - { - ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel); + public Vector3 GetNearestAllowedPosition(ScenePresence avatar) + { + return GetNearestAllowedPosition(avatar, null); + } - if (nearestParcel != null) - { - Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1)); - //Try to get a location that feels like where they came from - Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); - if (nearestPoint != null) - { - m_log.Debug("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString()); - return nearestPoint.Value; - } - - //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel - Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition); - dir = Vector3.Normalize(directionToParcelCenter); - nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); - if (nearestPoint != null) - { - m_log.Debug("They had a zero velocity, sending them to: " + nearestPoint.ToString()); - return nearestPoint.Value; - } - - ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y); - if (dest != excludeParcel) - { - // Ultimate backup if we have no idea where they are and - // the last allowed position was in another parcel - m_log.Debug("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString()); - return avatar.lastKnownAllowedPosition; - } - - // else fall through to region edge - } - - //Go to the edge, this happens in teleporting to a region with no available parcels - Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); - - //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); - - return nearestRegionEdgePoint; - } - - private Vector3 GetParcelCenterAtGround(ILandObject parcel) - { - Vector2 center = GetParcelCenter(parcel); - return GetPositionAtGround(center.X, center.Y); - } - - private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel) - { - Vector3 unitDirection = Vector3.Normalize(direction); - //Making distance to search go through some sane limit of distance - for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f) - { - Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); - if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) - { - return testPos; - } - } - return null; - } - - public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) - { - return GetNearestAllowedParcel(avatarId, x, y, null); - } - - public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel) - { - List all = AllParcels(); - float minParcelDistance = float.MaxValue; - ILandObject nearestParcel = null; - - foreach (var parcel in all) - { - if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel) - { - float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); - if (parcelDistance < minParcelDistance) - { - minParcelDistance = parcelDistance; - nearestParcel = parcel; - } - } - } - - return nearestParcel; - } - - private List AllParcels() - { - return LandChannel.AllParcels(); - } - - private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y) - { - return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel)); - } - - //calculate the average center point of a parcel - private Vector2 GetParcelCenter(ILandObject parcel) - { - int count = 0; - int avgx = 0; - int avgy = 0; - for (int x = 0; x < RegionInfo.RegionSizeX; x++) - { - for (int y = 0; y < RegionInfo.RegionSizeY; y++) - { - //Just keep a running average as we check if all the points are inside or not - if (parcel.ContainsPoint(x, y)) - { - if (count == 0) - { - avgx = x; - avgy = y; - } - else - { - avgx = (avgx * count + x) / (count + 1); - avgy = (avgy * count + y) / (count + 1); - } - count += 1; - } - } - } - return new Vector2(avgx, avgy); - } - - private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) - { - float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2 - ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X; - float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2 - ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y; - - //find out what vertical edge to go to - if (xdistance < ydistance) - { - if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2) - { - return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); + public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel) + { + ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel); + + if (nearestParcel != null) + { + Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1)); + //Try to get a location that feels like where they came from + Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); + if (nearestPoint != null) + { + m_log.Debug("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString()); + return nearestPoint.Value; + } + + //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel + Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition); + dir = Vector3.Normalize(directionToParcelCenter); + nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); + if (nearestPoint != null) + { + m_log.Debug("They had a zero velocity, sending them to: " + nearestPoint.ToString()); + return nearestPoint.Value; + } + + ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y); + if (dest != excludeParcel) + { + // Ultimate backup if we have no idea where they are and + // the last allowed position was in another parcel + m_log.Debug("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString()); + return avatar.lastKnownAllowedPosition; + } + + // else fall through to region edge + } + + //Go to the edge, this happens in teleporting to a region with no available parcels + Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); + + //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); + + return nearestRegionEdgePoint; + } + + private Vector3 GetParcelCenterAtGround(ILandObject parcel) + { + Vector2 center = GetParcelCenter(parcel); + return GetPositionAtGround(center.X, center.Y); + } + + private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel) + { + Vector3 unitDirection = Vector3.Normalize(direction); + //Making distance to search go through some sane limit of distance + for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f) + { + Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); + if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) + { + return testPos; + } } + return null; + } + + public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) + { + return GetNearestAllowedParcel(avatarId, x, y, null); + } + + public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel) + { + List all = AllParcels(); + float minParcelDistance = float.MaxValue; + ILandObject nearestParcel = null; + + foreach (var parcel in all) + { + if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel) + { + float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); + if (parcelDistance < minParcelDistance) + { + minParcelDistance = parcelDistance; + nearestParcel = parcel; + } + } + } + + return nearestParcel; + } + + private List AllParcels() + { + return LandChannel.AllParcels(); + } + + private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y) + { + return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel)); + } + + //calculate the average center point of a parcel + private Vector2 GetParcelCenter(ILandObject parcel) + { + int count = 0; + int avgx = 0; + int avgy = 0; + for (int x = 0; x < RegionInfo.RegionSizeX; x++) + { + for (int y = 0; y < RegionInfo.RegionSizeY; y++) + { + //Just keep a running average as we check if all the points are inside or not + if (parcel.ContainsPoint(x, y)) + { + if (count == 0) + { + avgx = x; + avgy = y; + } + else + { + avgx = (avgx * count + x) / (count + 1); + avgy = (avgy * count + y) / (count + 1); + } + count += 1; + } + } + } + return new Vector2(avgx, avgy); + } + + private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) + { + float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2 + ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X; + float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2 + ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y; + + //find out what vertical edge to go to + if (xdistance < ydistance) + { + if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2) + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); + } + else + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y); + } + } + //find out what horizontal edge to go to else { - return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y); + if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2) + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); + } + else + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY); + } } - } - //find out what horizontal edge to go to - else - { - if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2) + } + + private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y) + { + Vector3 ground = GetPositionAtGround(x, y); + if (avatar.AbsolutePosition.Z > ground.Z) { - return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); + ground.Z = avatar.AbsolutePosition.Z; } - else - { - return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY); - } - } - } - - private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y) - { - Vector3 ground = GetPositionAtGround(x, y); - if (avatar.AbsolutePosition.Z > ground.Z) - { - ground.Z = avatar.AbsolutePosition.Z; - } - return ground; - } - - private Vector3 GetPositionAtGround(float x, float y) - { - return new Vector3(x, y, GetGroundHeight(x, y)); - } - - public List GetEstateRegions(int estateID) - { - IEstateDataService estateDataService = EstateDataService; - if (estateDataService == null) - return new List(0); + return ground; + } - return estateDataService.GetRegions(estateID); - } + private Vector3 GetPositionAtGround(float x, float y) + { + return new Vector3(x, y, GetGroundHeight(x, y)); + } - public void ReloadEstateData() - { - IEstateDataService estateDataService = EstateDataService; - if (estateDataService != null) - { - RegionInfo.EstateSettings = estateDataService.LoadEstateSettings(RegionInfo.RegionID, false); - TriggerEstateSunUpdate(); - } - } - - public void TriggerEstateSunUpdate() - { - EventManager.TriggerEstateToolsSunUpdate(RegionInfo.RegionHandle); - } - - private void HandleReloadEstate(string module, string[] cmd) - { - if (MainConsole.Instance.ConsoleScene == null || - (MainConsole.Instance.ConsoleScene is Scene && - (Scene)MainConsole.Instance.ConsoleScene == this)) - { - ReloadEstateData(); - } - } - - /// - /// Get the volume of space that will encompass all the given objects. - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static Vector3[] GetCombinedBoundingBox( - List objects, - out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) - { - minX = float.MaxValue; - maxX = float.MinValue; - minY = float.MaxValue; - maxY = float.MinValue; - minZ = float.MaxValue; - maxZ = float.MinValue; - - List offsets = new List(); - - foreach (SceneObjectGroup g in objects) - { - float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; - - Vector3 vec = g.AbsolutePosition; - - g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); - - // m_log.DebugFormat( - // "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}", - // g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ)); - - ominX += vec.X; - omaxX += vec.X; - ominY += vec.Y; - omaxY += vec.Y; - ominZ += vec.Z; - omaxZ += vec.Z; - - if (minX > ominX) - minX = ominX; - if (minY > ominY) - minY = ominY; - if (minZ > ominZ) - minZ = ominZ; - if (maxX < omaxX) - maxX = omaxX; - if (maxY < omaxY) - maxY = omaxY; - if (maxZ < omaxZ) - maxZ = omaxZ; - } - - foreach (SceneObjectGroup g in objects) - { - Vector3 vec = g.AbsolutePosition; - vec.X -= minX; - vec.Y -= minY; - vec.Z -= minZ; - - offsets.Add(vec); - } - - return offsets.ToArray(); - } - - /// - /// Regenerate the maptile for this scene. - /// - /// - /// - private void RegenerateMaptile() - { - IWorldMapModule mapModule = RequestModuleInterface(); - if (mapModule != null) + public List GetEstateRegions(int estateID) + { + IEstateDataService estateDataService = EstateDataService; + if (estateDataService == null) + return new List(0); + + return estateDataService.GetRegions(estateID); + } + + public void ReloadEstateData() + { + IEstateDataService estateDataService = EstateDataService; + if (estateDataService != null) + { + RegionInfo.EstateSettings = estateDataService.LoadEstateSettings(RegionInfo.RegionID, false); + TriggerEstateSunUpdate(); + } + } + + public void TriggerEstateSunUpdate() + { + EventManager.TriggerEstateToolsSunUpdate(RegionInfo.RegionHandle); + } + + private void HandleReloadEstate(string module, string[] cmd) + { + if (MainConsole.Instance.ConsoleScene == null || + (MainConsole.Instance.ConsoleScene is Scene && + (Scene)MainConsole.Instance.ConsoleScene == this)) + { + ReloadEstateData(); + } + } + + /// + /// Get the volume of space that will encompass all the given objects. + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static Vector3[] GetCombinedBoundingBox( + List objects, + out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) + { + minX = float.MaxValue; + maxX = float.MinValue; + minY = float.MaxValue; + maxY = float.MinValue; + minZ = float.MaxValue; + maxZ = float.MinValue; + + List offsets = new List(); + + foreach (SceneObjectGroup g in objects) + { + float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; + + Vector3 vec = g.AbsolutePosition; + + g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); + + // m_log.DebugFormat( + // "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}", + // g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ)); + + ominX += vec.X; + omaxX += vec.X; + ominY += vec.Y; + omaxY += vec.Y; + ominZ += vec.Z; + omaxZ += vec.Z; + + if (minX > ominX) + minX = ominX; + if (minY > ominY) + minY = ominY; + if (minZ > ominZ) + minZ = ominZ; + if (maxX < omaxX) + maxX = omaxX; + if (maxY < omaxY) + maxY = omaxY; + if (maxZ < omaxZ) + maxZ = omaxZ; + } + + foreach (SceneObjectGroup g in objects) + { + Vector3 vec = g.AbsolutePosition; + vec.X -= minX; + vec.Y -= minY; + vec.Z -= minZ; + + offsets.Add(vec); + } + + return offsets.ToArray(); + } + + /// + /// Regenerate the maptile for this scene. + /// + /// + /// + private void RegenerateMaptile() + { + IWorldMapModule mapModule = RequestModuleInterface(); + if (mapModule != null) mapModule.GenerateMaptile(); - } + } - private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) - { - RegenerateMaptile(); + private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) + { + RegenerateMaptile(); - // We need to propagate the new image UUID to the grid service - // so that all simulators can retrieve it - string error = GridService.RegisterRegion(RegionInfo.ScopeID, new GridRegion(RegionInfo)); - if (error != string.Empty) + // We need to propagate the new image UUID to the grid service + // so that all simulators can retrieve it + string error = GridService.RegisterRegion(RegionInfo.ScopeID, new GridRegion(RegionInfo)); + if (error != string.Empty) throw new Exception(error); - } - - /// - /// This method is called across the simulation connector to - /// determine if a given agent is allowed in this region - /// AS A ROOT AGENT - /// - /// - /// Returning false here will prevent them - /// from logging into the region, teleporting into the region - /// or corssing the broder walking, but will NOT prevent - /// child agent creation, thereby emulating the SL behavior. - /// - /// The visitor's User ID - /// The visitor's Home URI (may be null) - /// - /// - /// - public bool QueryAccess(UUID agentID, string agentHomeURI, bool viaTeleport, Vector3 position, out string reason) - { - reason = string.Empty; - - if (Permissions.IsGod(agentID)) - { - reason = String.Empty; - return true; - } - - if (!AllowAvatarCrossing && !viaTeleport) + } + + /// + /// This method is called across the simulation connector to + /// determine if a given agent is allowed in this region + /// AS A ROOT AGENT + /// + /// + /// Returning false here will prevent them + /// from logging into the region, teleporting into the region + /// or corssing the broder walking, but will NOT prevent + /// child agent creation, thereby emulating the SL behavior. + /// + /// The visitor's User ID + /// The visitor's Home URI (may be null) + /// + /// + /// + public bool QueryAccess(UUID agentID, string agentHomeURI, bool viaTeleport, Vector3 position, out string reason) + { + reason = string.Empty; + + if (Permissions.IsGod(agentID)) + { + reason = String.Empty; + return true; + } + + if (!AllowAvatarCrossing && !viaTeleport) return false; - // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. - // However, the long term fix is to make sure root agent count is always accurate. - m_sceneGraph.RecalculateStats(); + // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. + // However, the long term fix is to make sure root agent count is always accurate. + m_sceneGraph.RecalculateStats(); - int num = m_sceneGraph.GetRootAgentCount(); + int num = m_sceneGraph.GetRootAgentCount(); - if (num >= RegionInfo.RegionSettings.AgentLimit) - { - if (!Permissions.IsAdministrator(agentID)) + if (num >= RegionInfo.RegionSettings.AgentLimit) { - reason = "The region is full"; + if (!Permissions.IsAdministrator(agentID)) + { + reason = "The region is full"; - m_log.DebugFormat( - "[SCENE]: Denying presence with id {0} entry into {1} since region is at agent limit of {2}", - agentID, RegionInfo.RegionName, RegionInfo.RegionSettings.AgentLimit); + m_log.DebugFormat( + "[SCENE]: Denying presence with id {0} entry into {1} since region is at agent limit of {2}", + agentID, RegionInfo.RegionName, RegionInfo.RegionSettings.AgentLimit); - return false; + return false; + } } - } - - ScenePresence presence = GetScenePresence(agentID); - IClientAPI client = null; - AgentCircuitData aCircuit = null; - if (presence != null) - { - client = presence.ControllingClient; - if (client != null) - aCircuit = client.RequestClientInfo(); - } - - // We may be called before there is a presence or a client. - // Fake AgentCircuitData to keep IAuthorizationModule smiling - if (client == null) - { - aCircuit = new AgentCircuitData(); - aCircuit.AgentID = agentID; - aCircuit.firstname = String.Empty; - aCircuit.lastname = String.Empty; - } + ScenePresence presence = GetScenePresence(agentID); + IClientAPI client = null; + AgentCircuitData aCircuit = null; - try - { - if (!AuthorizeUser(aCircuit, false, out reason)) + if (presence != null) { - //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); - return false; - } - } - catch (Exception e) - { - m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} " + e.StackTrace, e.Message); - reason = "Error authorizing agent: " + e.Message; - return false; - } - - if (viaTeleport) - { - if (!RegionInfo.EstateSettings.AllowDirectTeleport) - { - SceneObjectGroup telehub; - if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject)) != null) - { - List spawnPoints = RegionInfo.RegionSettings.SpawnPoints(); - bool banned = true; - foreach (SpawnPoint sp in spawnPoints) - { - Vector3 spawnPoint = sp.GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); - ILandObject land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); - if (land == null) - continue; - if (land.IsEitherBannedOrRestricted(agentID)) - continue; - banned = false; - break; - } - - if (banned) - { - if (Permissions.IsAdministrator(agentID) == false || Permissions.IsGridGod(agentID) == false) - { - reason = "No suitable landing point found"; - return false; - } - reason = "Administrative access only"; - return true; - } - } + client = presence.ControllingClient; + if (client != null) + aCircuit = client.RequestClientInfo(); } - float posX = 128.0f; - float posY = 128.0f; - - if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY)) - { - // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID); - reason = "You are banned from the region on all parcels"; - return false; - } - } - else // Walking - { - ILandObject land = LandChannel.GetLandObject(position.X, position.Y); - if (land == null) + // We may be called before there is a presence or a client. + // Fake AgentCircuitData to keep IAuthorizationModule smiling + if (client == null) { - reason = "No parcel found"; - return false; + aCircuit = new AgentCircuitData(); + aCircuit.AgentID = agentID; + aCircuit.firstname = String.Empty; + aCircuit.lastname = String.Empty; } - bool banned = land.IsBannedFromLand(agentID); - bool restricted = land.IsRestrictedFromLand(agentID); - - if (banned || restricted) + try { - if (banned) - reason = "You are banned from the parcel"; - else - reason = "The parcel is restricted"; - return false; - } - } - - reason = String.Empty; - return true; - } - - /// - /// This method deals with movement when an avatar is automatically moving (but this is distinct from the - /// autopilot that moves an avatar to a sit target!. - /// - /// - /// This is not intended as a permament location for this method. - /// - /// - private void HandleOnSignificantClientMovement(ScenePresence presence) - { - if (presence.MovingToTarget) - { - double distanceToTarget = Util.GetDistanceTo(presence.AbsolutePosition, presence.MoveToPositionTarget); - // m_log.DebugFormat( - // "[SCENE]: Abs pos of {0} is {1}, target {2}, distance {3}", - // presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget, distanceToTarget); - - // Check the error term of the current position in relation to the target position - if (distanceToTarget <= ScenePresence.SIGNIFICANT_MOVEMENT) - { - // We are close enough to the target - // m_log.DebugFormat("[SCENEE]: Stopping autopilot of {0}", presence.Name); - - presence.Velocity = Vector3.Zero; - presence.AbsolutePosition = presence.MoveToPositionTarget; - presence.ResetMoveToTarget(); - - if (presence.Flying) - { - // A horrible hack to stop the avatar dead in its tracks rather than having them overshoot - // the target if flying. - // We really need to be more subtle (slow the avatar as it approaches the target) or at - // least be able to set collision status once, rather than 5 times to give it enough - // weighting so that that PhysicsActor thinks it really is colliding. - for (int i = 0; i < 5; i++) - presence.IsColliding = true; - - if (presence.LandAtTarget) - presence.Flying = false; - - // Vector3 targetPos = presence.MoveToPositionTarget; - // float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y]; - // if (targetPos.Z - terrainHeight < 0.2) - // { - // presence.Flying = false; - // } - } - - // m_log.DebugFormat( - // "[SCENE]: AgentControlFlags {0}, MovementFlag {1} for {2}", - // presence.AgentControlFlags, presence.MovementFlag, presence.Name); + if (!AuthorizeUser(aCircuit, false, out reason)) + { + //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); + return false; + } } - else + catch (Exception e) { - // m_log.DebugFormat( - // "[SCENE]: Updating npc {0} at {1} for next movement to {2}", - // presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget); - - Vector3 agent_control_v3 = new Vector3(); - presence.HandleMoveToTargetUpdate(1, ref agent_control_v3); - presence.AddNewMovement(agent_control_v3); + m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} " + e.StackTrace, e.Message); + reason = "Error authorizing agent: " + e.Message; + return false; + } + + if (viaTeleport) + { + if (!RegionInfo.EstateSettings.AllowDirectTeleport) + { + SceneObjectGroup telehub; + if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject)) != null) + { + List spawnPoints = RegionInfo.RegionSettings.SpawnPoints(); + bool banned = true; + foreach (SpawnPoint sp in spawnPoints) + { + Vector3 spawnPoint = sp.GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + ILandObject land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); + if (land == null) + continue; + if (land.IsEitherBannedOrRestricted(agentID)) + continue; + banned = false; + break; + } + + if (banned) + { + if (Permissions.IsAdministrator(agentID) == false || Permissions.IsGridGod(agentID) == false) + { + reason = "No suitable landing point found"; + return false; + } + reason = "Administrative access only"; + return true; + } + } + } + + float posX = 128.0f; + float posY = 128.0f; + + if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY)) + { + // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID); + reason = "You are banned from the region on all parcels"; + return false; + } + } + else // Walking + { + ILandObject land = LandChannel.GetLandObject(position.X, position.Y); + if (land == null) + { + reason = "No parcel found"; + return false; + } + + bool banned = land.IsBannedFromLand(agentID); + bool restricted = land.IsRestrictedFromLand(agentID); + + if (banned || restricted) + { + if (banned) + reason = "You are banned from the parcel"; + else + reason = "The parcel is restricted"; + return false; + } } - } - } - // manage and select spawn points in sequence - public int SpawnPoint() - { - int spawnpoints = RegionInfo.RegionSettings.SpawnPoints().Count; - - if (spawnpoints == 0) + reason = String.Empty; + return true; + } + + /// + /// This method deals with movement when an avatar is automatically moving (but this is distinct from the + /// autopilot that moves an avatar to a sit target!. + /// + /// + /// This is not intended as a permament location for this method. + /// + /// + private void HandleOnSignificantClientMovement(ScenePresence presence) + { + if (presence.MovingToTarget) + { + double distanceToTarget = Util.GetDistanceTo(presence.AbsolutePosition, presence.MoveToPositionTarget); + // m_log.DebugFormat( + // "[SCENE]: Abs pos of {0} is {1}, target {2}, distance {3}", + // presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget, distanceToTarget); + + // Check the error term of the current position in relation to the target position + if (distanceToTarget <= ScenePresence.SIGNIFICANT_MOVEMENT) + { + // We are close enough to the target + // m_log.DebugFormat("[SCENEE]: Stopping autopilot of {0}", presence.Name); + + presence.Velocity = Vector3.Zero; + presence.AbsolutePosition = presence.MoveToPositionTarget; + presence.ResetMoveToTarget(); + + if (presence.Flying) + { + // A horrible hack to stop the avatar dead in its tracks rather than having them overshoot + // the target if flying. + // We really need to be more subtle (slow the avatar as it approaches the target) or at + // least be able to set collision status once, rather than 5 times to give it enough + // weighting so that that PhysicsActor thinks it really is colliding. + for (int i = 0; i < 5; i++) + presence.IsColliding = true; + + if (presence.LandAtTarget) + presence.Flying = false; + + // Vector3 targetPos = presence.MoveToPositionTarget; + // float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y]; + // if (targetPos.Z - terrainHeight < 0.2) + // { + // presence.Flying = false; + // } + } + + // m_log.DebugFormat( + // "[SCENE]: AgentControlFlags {0}, MovementFlag {1} for {2}", + // presence.AgentControlFlags, presence.MovementFlag, presence.Name); + } + else + { + // m_log.DebugFormat( + // "[SCENE]: Updating npc {0} at {1} for next movement to {2}", + // presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget); + + Vector3 agent_control_v3 = new Vector3(); + presence.HandleMoveToTargetUpdate(1, ref agent_control_v3); + presence.AddNewMovement(agent_control_v3); + } + } + } + + // manage and select spawn points in sequence + public int SpawnPoint() + { + int spawnpoints = RegionInfo.RegionSettings.SpawnPoints().Count; + + if (spawnpoints == 0) return 0; - m_SpawnPoint++; - if (m_SpawnPoint > spawnpoints) + m_SpawnPoint++; + if (m_SpawnPoint > spawnpoints) m_SpawnPoint = 1; - return m_SpawnPoint - 1; - } - - /// - /// Wrappers to get physics modules retrieve assets. - /// - /// - /// Has to be done this way - /// because we can't assign the asset service to physics directly - at the - /// time physics are instantiated it's not registered but it will be by - /// the time the first prim exists. - /// - /// - /// - public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback) - { - AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived); - } - - private void PhysicsAssetReceived(string id, Object sender, AssetBase asset) - { - AssetReceivedDelegate callback = (AssetReceivedDelegate)sender; - - callback(asset); - } - - public string GetExtraSetting(string name) - { - if (m_extraSettings == null) + return m_SpawnPoint - 1; + } + + /// + /// Wrappers to get physics modules retrieve assets. + /// + /// + /// Has to be done this way + /// because we can't assign the asset service to physics directly - at the + /// time physics are instantiated it's not registered but it will be by + /// the time the first prim exists. + /// + /// + /// + public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback) + { + AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived); + } + + private void PhysicsAssetReceived(string id, Object sender, AssetBase asset) + { + AssetReceivedDelegate callback = (AssetReceivedDelegate)sender; + + callback(asset); + } + + public string GetExtraSetting(string name) + { + if (m_extraSettings == null) return String.Empty; - string val; + string val; - if (!m_extraSettings.TryGetValue(name, out val)) + if (!m_extraSettings.TryGetValue(name, out val)) return String.Empty; - return val; - } + return val; + } - public void StoreExtraSetting(string name, string val) - { - if (m_extraSettings == null) + public void StoreExtraSetting(string name, string val) + { + if (m_extraSettings == null) return; - string oldVal; + string oldVal; - if (m_extraSettings.TryGetValue(name, out oldVal)) - { - if (oldVal == val) - return; - } + if (m_extraSettings.TryGetValue(name, out oldVal)) + { + if (oldVal == val) + return; + } - m_extraSettings[name] = val; + m_extraSettings[name] = val; - m_SimulationDataService.SaveExtra(RegionInfo.RegionID, name, val); + m_SimulationDataService.SaveExtra(RegionInfo.RegionID, name, val); - m_eventManager.TriggerExtraSettingChanged(this, name, val); - } + m_eventManager.TriggerExtraSettingChanged(this, name, val); + } - public void RemoveExtraSetting(string name) - { - if (m_extraSettings == null) + public void RemoveExtraSetting(string name) + { + if (m_extraSettings == null) return; - if (!m_extraSettings.ContainsKey(name)) + if (!m_extraSettings.ContainsKey(name)) return; - m_extraSettings.Remove(name); + m_extraSettings.Remove(name); - m_SimulationDataService.RemoveExtra(RegionInfo.RegionID, name); + m_SimulationDataService.RemoveExtra(RegionInfo.RegionID, name); - m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty); - } - } + m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty); + } + } } diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 07d5f04..8918c3b 100755 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -228,7 +228,7 @@ namespace OpenSim.Region.Framework.Scenes // the Total, Simulation, Physics, and Network Frame Time; It is set to // 10 by default but can be changed by the OpenSim.ini configuration file // NumberOfFrames parameter - private int m_numberFramesStored = 10; + private int m_numberFramesStored = Scene.m_defaultNumberFramesStored; // The arrays that will hold the time it took to run the past N frames, // where N is the num_frames_to_average given by the configuration file -- cgit v1.1 From c4a3c93097c9a1c1b93f5b86dfc0f17062e42c30 Mon Sep 17 00:00:00 2001 From: Steven Zielinski Date: Fri, 1 May 2015 17:07:19 -0400 Subject: Fixed a bug that would cause the sim extra stats reporter to fail in reporting stats. The bug was caused by the current process threads which can return null references. Test Plan: Tested on windows using opensim standalone and the json stats. Reviewers: rlouden, kboswell, clattin, martin, ssirigam Differential Revision: http://cr.irl.ucf.edu/D277 --- OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index 432efdb..83d9e85 100755 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs @@ -433,7 +433,11 @@ Asset service request failures: {3}" + Environment.NewLine, foreach (ProcessThread currentThread in Process.GetCurrentProcess().Threads) { - if (currentThread.ThreadState == ThreadState.Running) + // A known issue with the current process .threads method is + // that it can return null threads, thus don't count those as + // running threads and prevent the program function from failing + if (currentThread != null && + currentThread.ThreadState == ThreadState.Running) { numberThreadsRunning++; } -- cgit v1.1 From cb517839e9e258d154e17fe85e97f1462b06536a Mon Sep 17 00:00:00 2001 From: Steven Zielinski Date: Mon, 4 May 2015 10:05:36 -0400 Subject: Fixed vocabulary in a comment to match the code. --- OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index 83d9e85..3791fff 100755 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs @@ -433,7 +433,7 @@ Asset service request failures: {3}" + Environment.NewLine, foreach (ProcessThread currentThread in Process.GetCurrentProcess().Threads) { - // A known issue with the current process .threads method is + // A known issue with the current process .threads property is // that it can return null threads, thus don't count those as // running threads and prevent the program function from failing if (currentThread != null && -- cgit v1.1 From 96a86e7d5a4a4f0d712522190a1ff19fc44aac80 Mon Sep 17 00:00:00 2001 From: Steven Zielinski Date: Mon, 4 May 2015 10:40:36 -0400 Subject: Fixed a bug that would cause the sim extra stats reporter to fail in reporting stats. The bug was caused by the current process threads which can return null references. Test Plan: Tested on windows using opensim standalone and the json stats. Reviewers: rlouden, ssirigam, clattin, martin, kboswell Reviewed By: rlouden, ssirigam, clattin, martin, kboswell Differential Revision: http://cr.irl.ucf.edu/D277 --- OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index 3791fff..e4df7ee 100755 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs @@ -433,7 +433,7 @@ Asset service request failures: {3}" + Environment.NewLine, foreach (ProcessThread currentThread in Process.GetCurrentProcess().Threads) { - // A known issue with the current process .threads property is + // A known issue with the current process .Threads property is // that it can return null threads, thus don't count those as // running threads and prevent the program function from failing if (currentThread != null && -- cgit v1.1 From d52f58a7339aba40035f9bcc1f5b26232c714c48 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 12 May 2015 19:54:25 +0100 Subject: Disable the "show threadpool calls active" console command for now. Whilst this can be very useful to identify threads held too long by incoming packet processing, it can also be very misleading as the count updates are not atomic (race conditions lead to growth in numbers over time). This could be solved by making the counts volatile but I don't currently have time to assess the performance impact, though it's almost certainly negligible. If anybody else wants to do that and re-enable this command then please feel free. --- OpenSim/Framework/Servers/ServerBase.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index c22c119..e403ba0 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -292,11 +292,11 @@ namespace OpenSim.Framework.Servers + " 3 = full stack trace, including common threads\n", HandleDebugThreadpoolLevel); - m_console.Commands.AddCommand( - "Debug", false, "show threadpool calls active", - "show threadpool calls active", - "Show details about threadpool calls that are still active (currently waiting or in progress)", - HandleShowThreadpoolCallsActive); +// m_console.Commands.AddCommand( +// "Debug", false, "show threadpool calls active", +// "show threadpool calls active", +// "Show details about threadpool calls that are still active (currently waiting or in progress)", +// HandleShowThreadpoolCallsActive); m_console.Commands.AddCommand( "Debug", false, "show threadpool calls complete", -- cgit v1.1 From d348f871612c5f241f33885604391d1f30a416bc Mon Sep 17 00:00:00 2001 From: Magnuz Binder Date: Sun, 10 May 2015 20:01:50 +0200 Subject: Patch llCastRay fully simplified to V3. --- .../Shared/Api/Implementation/LSL_Api.cs | 429 +++++++++++---------- bin/OpenSimDefaults.ini | 46 ++- 2 files changed, 248 insertions(+), 227 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index c90f015..089a5a8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -221,15 +221,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected float m_primSafetyCoeffX = 2.414214f; protected float m_primSafetyCoeffY = 2.414214f; protected float m_primSafetyCoeffZ = 1.618034f; + protected bool m_useCastRayV3 = false; protected float m_floatToleranceInCastRay = 0.000001f; protected float m_floatTolerance2InCastRay = 0.0001f; + protected DetailLevel m_primLodInCastRay = DetailLevel.Medium; + protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium; + protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest; + protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium; protected int m_maxHitsInCastRay = 16; protected int m_maxHitsPerPrimInCastRay = 16; protected int m_maxHitsPerObjectInCastRay = 16; protected bool m_detectExitsInCastRay = false; protected bool m_filterPartsInCastRay = false; protected bool m_doAttachmentsInCastRay = false; - protected bool m_useCastRayV1 = true; //An array of HTTP/1.1 headers that are not allowed to be used //as custom headers by llHTTPRequest. @@ -336,15 +340,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX); m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY); m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ); + m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3); m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); + m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay); + m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay); + m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay); + m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay); m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay); m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay); m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); - m_useCastRayV1 = lslConfig.GetBoolean("UseLlCastRayV1", m_useCastRayV1); } IConfig smtpConfig = seConfigSource.Configs["SMTP"]; @@ -13811,8 +13819,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return contacts[0]; } - public LSL_List llCastRayV1(LSL_Vector start, LSL_Vector end, LSL_List options) + public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) { + // Use llCastRay V3 if configured + if (m_useCastRayV3) + return llCastRayV3(start, end, options); + LSL_List list = new LSL_List(); m_host.AddScriptLPS(1); @@ -14003,29 +14015,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Full implementation of llCastRay similar to SL 2015-04-21. + /// Implementation of llCastRay similar to SL 2015-04-21. /// http://wiki.secondlife.com/wiki/LlCastRay /// Uses pure geometry, bounding shapes, meshing and no physics /// for prims, sculpts, meshes, avatars and terrain. /// Implements all flags, reject types and data flags. /// Can handle both objects/groups and prims/parts, by config. - /// May give poor results with multi-part meshes where "root" - /// part doesn't dominate, owing to "guessed" bounding boxes. - /// May sometimes be inaccurate owing to calculation precision - /// and a bug in libopenmetaverse PrimMesher. + /// May sometimes be inaccurate owing to calculation precision, + /// meshing detail level and a bug in libopenmetaverse PrimMesher. /// - public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) + public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options) { - // Use llCastRay v1 if configured - if (m_useCastRayV1) - return llCastRayV1(start, end, options); - // Initialize m_host.AddScriptLPS(1); List rayHits = new List(); LSL_List result = new LSL_List(); float tol = m_floatToleranceInCastRay; - float tol2 = m_floatTolerance2InCastRay; + Vector3 pos1Ray = start; + Vector3 pos2Ray = end; // Get input options int rejectTypes = 0; @@ -14054,25 +14061,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0); // Calculate some basic parameters - Vector3 ray = end - start; - float rayLength = ray.Length(); + Vector3 vecRay = pos2Ray - pos1Ray; + float rayLength = vecRay.Length(); - // Try to get a mesher and return failure if none or degenerate ray + // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits IRendering primMesher = null; List renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); - if (renderers.Count < 1 || rayLength < tol) + if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1) { result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); return result; } primMesher = RenderingLoader.LoadRenderer(renderers[0]); - // Used to translate and rotate world so ray is along negative Z axis from origo and - // calculations mostly simplified to a 2D projecttion on the X-Y plane - Vector3 posProj = new Vector3(-start); - Quaternion rotProj = Vector3.RotationBetween(ray, new Vector3(0.0f, 0.0f, -1.0f)); - Quaternion rotBack = Quaternion.Inverse(rotProj); - // Iterate over all objects/groups and prims/parts in region World.ForEachSOG( delegate(SceneObjectGroup group) @@ -14115,51 +14116,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!doPart) continue; } - // Parse prim/part if passed filters - // Estimate bounding box from size box - Vector3 scaleSafe = part.Scale; - if (!part.Shape.SculptEntry) - scaleSafe = scaleSafe * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); + // Parse prim/part and project ray if passed filters + Vector3 scalePart = part.Scale; + Vector3 posPart = part.GetWorldPosition(); + Quaternion rotPart = part.GetWorldRotation(); + Quaternion rotPartInv = Quaternion.Inverse(rotPart); + Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; + Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; - // Filter parts by bounding shapes - Vector3 posPartRel = part.GetWorldPosition() + posProj; - Vector3 posPartProj = posPartRel * rotProj; - if (InBoundingShapes(ray, rayLength, scaleSafe, posPartRel, posPartProj, rotProj)) + // Filter parts by shape bounding boxes + Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f); + if (!part.Shape.SculptEntry) + shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); + shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol)); + if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) { // Prepare data needed to check for ray hits RayTrans rayTrans = new RayTrans(); rayTrans.PartId = part.UUID; rayTrans.GroupId = part.ParentGroup.UUID; rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0; - rayTrans.Scale = part.Scale; - rayTrans.PositionPartProj = posPartProj; - rayTrans.PositionProj = posProj; - rayTrans.RotationPartProj = rotProj * part.GetWorldRotation(); - rayTrans.RotationBack = rotBack; - rayTrans.NeedsEnds = true; - rayTrans.RayLength = rayLength; - rayTrans.Tolerance = tol; - rayTrans.Tolerance2 = tol2; + rayTrans.ScalePart = scalePart; + rayTrans.PositionPart = posPart; + rayTrans.RotationPart = rotPart; + rayTrans.ShapeNeedsEnds = true; + rayTrans.Position1Ray = pos1Ray; + rayTrans.Position1RayProj = pos1RayProj; + rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; // Make an OMV prim to be able to mesh part - Primitive omvPrim = part.Shape.ToOmvPrimitive(posPartProj, rayTrans.RotationPartProj); + Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); byte[] sculptAsset = null; if (omvPrim.Sculpt != null) sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); + FacetedMesh mesh = null; - // When part is mesh, get and check mesh + // When part is mesh, get mesh and check for hits if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) { AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); - FacetedMesh mesh = null; - FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh); + FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); meshAsset = null; - AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); - mesh = null; } - // When part is sculpt, create and check mesh + // When part is sculpt, create mesh and check for hits // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) { @@ -14169,15 +14170,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api Image sculpt = imgDecoder.DecodeToImage(sculptAsset); if (sculpt != null) { - SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); + mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); sculpt.Dispose(); - AddRayInSimpleMesh(mesh, rayTrans, ref rayHits); - mesh = null; } } } - // When part is prim, create and check mesh + // When part is prim, create mesh and check for hits else if (omvPrim.Sculpt == null) { if ( @@ -14186,12 +14185,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api omvPrim.PrimData.PathSkew == 0.0 && omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 ) - rayTrans.NeedsEnds = false; - SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); - AddRayInSimpleMesh(mesh, rayTrans, ref rayHits); - mesh = null; + rayTrans.ShapeNeedsEnds = false; + mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); } + // Check mesh for ray hits + AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); + mesh = null; } } } @@ -14205,38 +14205,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api World.ForEachRootScenePresence( delegate (ScenePresence sp) { - // Parse avatar - // Get bounding box Vector3 lower; Vector3 upper; BoundingBoxOfScenePresence(sp, out lower, out upper); - Vector3 scale = upper - lower; - - // Filter avatars by bounding shapes - Vector3 posPartRel = sp.AbsolutePosition + posProj + (lower + upper) * 0.5f * sp.Rotation; - Vector3 posPartProj = posPartRel * rotProj; - if (InBoundingShapes(ray, rayLength, scale, posPartRel, posPartProj, rotProj)) + // Parse avatar + Vector3 scalePart = upper - lower; + Vector3 posPart = sp.AbsolutePosition; + Quaternion rotPart = sp.GetWorldRotation(); + Quaternion rotPartInv = Quaternion.Inverse(rotPart); + posPart = posPart + (lower + upper) * 0.5f * rotPart; + // Project ray + Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; + Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; + + // Filter avatars by shape bounding boxes + Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol); + if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) { // Prepare data needed to check for ray hits RayTrans rayTrans = new RayTrans(); rayTrans.PartId = sp.UUID; rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID; rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0; - rayTrans.Scale = scale; - rayTrans.PositionPartProj = posPartProj; - rayTrans.PositionProj = posProj; - rayTrans.RotationPartProj = rotProj * sp.Rotation; - rayTrans.RotationBack = rotBack; - rayTrans.NeedsEnds = false; - rayTrans.RayLength = rayLength; - rayTrans.Tolerance = tol; - rayTrans.Tolerance2 = tol2; + rayTrans.ScalePart = scalePart; + rayTrans.PositionPart = posPart; + rayTrans.RotationPart = rotPart; + rayTrans.ShapeNeedsEnds = false; + rayTrans.Position1Ray = pos1Ray; + rayTrans.Position1RayProj = pos1RayProj; + rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; // Make OMV prim, create and check mesh - Primitive omvPrim = MakeOpenMetaversePrim(scale, posPartProj, rayTrans.RotationPartProj, ScriptBaseClass.PRIM_TYPE_SPHERE); - SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); - AddRayInSimpleMesh(mesh, rayTrans, ref rayHits); + PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere(); + prim.Scale = scalePart; + Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); + FacetedMesh mesh = primMesher.GenerateFacetedMesh(omvPrim, m_meshLodInCastRay); + AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); mesh = null; } } @@ -14248,32 +14253,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { // Parse terrain - // Mesh terrain and check projected bounding box - Vector3 posPartProj = posProj * rotProj; - Quaternion rotPartProj = rotProj; + // Mesh terrain and check bounding box Vector3 lower; Vector3 upper; - List triangles = TrisFromHeightmapUnderRay(start, end, out lower, out upper); - Vector3 lowerBox = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); - Vector3 upperBox = new Vector3(float.MinValue, float.MinValue, float.MinValue); - int dummy = 0; - AddBoundingBoxOfSimpleBox(lower, upper, posPartProj, rotPartProj, true, ref lowerBox, ref upperBox, ref dummy); - if (lowerBox.X <= tol && lowerBox.Y <= tol && lowerBox.Z <= tol && upperBox.X >= -tol && upperBox.Y >= -tol && upperBox.Z >= -rayLength - tol) + List triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper); + lower.Z -= tol; + upper.Z += tol; + if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z)) { // Prepare data needed to check for ray hits RayTrans rayTrans = new RayTrans(); rayTrans.PartId = UUID.Zero; rayTrans.GroupId = UUID.Zero; rayTrans.Link = 0; - rayTrans.Scale = new Vector3 (1.0f, 1.0f, 1.0f); - rayTrans.PositionPartProj = posPartProj; - rayTrans.PositionProj = posProj; - rayTrans.RotationPartProj = rotPartProj; - rayTrans.RotationBack = rotBack; - rayTrans.NeedsEnds = true; - rayTrans.RayLength = rayLength; - rayTrans.Tolerance = tol; - rayTrans.Tolerance2 = tol2; + rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f); + rayTrans.PositionPart = Vector3.Zero; + rayTrans.RotationPart = Quaternion.Identity; + rayTrans.ShapeNeedsEnds = true; + rayTrans.Position1Ray = pos1Ray; + rayTrans.Position1RayProj = pos1Ray; + rayTrans.VectorRayProj = vecRay; // Check mesh AddRayInTris(triangles, rayTrans, ref rayHits); @@ -14358,15 +14357,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public UUID PartId; public UUID GroupId; public int Link; - public Vector3 Scale; - public Vector3 PositionPartProj; - public Vector3 PositionProj; - public Quaternion RotationPartProj; - public Quaternion RotationBack; - public bool NeedsEnds; - public float RayLength; - public float Tolerance; - public float Tolerance2; + public Vector3 ScalePart; + public Vector3 PositionPart; + public Quaternion RotationPart; + public bool ShapeNeedsEnds; + public Vector3 Position1Ray; + public Vector3 Position1RayProj; + public Vector3 VectorRayProj; } /// @@ -14383,21 +14380,63 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Helper to parse SimpleMesh for ray hits. + /// Helper to check if a ray intersects a shape bounding box. /// - private void AddRayInSimpleMesh(SimpleMesh mesh, RayTrans rayTrans, ref List rayHits) - { - if (mesh != null) + private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax) + { + // Skip if ray can't intersect bounding box; + Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj); + Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj); + if ( + rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z || + rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z + ) + return false; + + // Check if ray intersect any bounding box side + int sign = 0; + float dist = 0.0f; + Vector3 posProj = Vector3.Zero; + Vector3 vecRayProj = pos2RayProj - pos1RayProj; + + // Check both X sides unless ray is parallell to them + if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay) + { + for (sign = -1; sign <= 1; sign += 2) + { + dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X; + posProj = pos1RayProj + vecRayProj * dist; + if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z) + return true; + } + } + + // Check both Y sides unless ray is parallell to them + if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay) { - for (int i = 0; i < mesh.Indices.Count; i += 3) + for (sign = -1; sign <= 1; sign += 2) { - Tri triangle = new Tri(); - triangle.p1 = mesh.Vertices[mesh.Indices[i]].Position; - triangle.p2 = mesh.Vertices[mesh.Indices[i + 1]].Position; - triangle.p3 = mesh.Vertices[mesh.Indices[i + 2]].Position; - AddRayInTri(triangle, rayTrans, ref rayHits); + dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y; + posProj = pos1RayProj + vecRayProj * dist; + if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z) + return true; } } + + // Check both Z sides unless ray is parallell to them + if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay) + { + for (sign = -1; sign <= 1; sign += 2) + { + dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z; + posProj = pos1RayProj + vecRayProj * dist; + if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y) + return true; + } + } + + // No hits on bounding box so return false + return false; } /// @@ -14409,7 +14448,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { foreach (Face face in mesh.Faces) { - for (int i = 0; i /// Helper to add ray hit in a Tri (triangle). /// - private void AddRayInTri(Tri triangle, RayTrans rayTrans, ref List rayHits) + private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List rayHits) { // Check for hit in triangle - float distance; - Vector3 posHit; - Vector3 normal; - if (HitRayInTri(triangle, rayTrans, out distance, out posHit, out normal)) - { - // Project hit part back to normal coordinate system - Vector3 posPart = rayTrans.PositionPartProj * rayTrans.RotationBack - rayTrans.PositionProj; - // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) faces plane through shape center - if (Math.Abs(Vector3.Dot(posPart, normal) - Vector3.Dot(posHit, normal)) < rayTrans.Tolerance && !rayTrans.NeedsEnds) + Vector3 posHitProj; + Vector3 normalProj; + if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj)) + { + // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center + if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds) return; - // Remove duplicate hits at triangle edges and intersections + + // Transform hit and normal to region coordinate system + Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart; + Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart); + + // Remove duplicate hits at triangle intersections + float distance = Vector3.Distance(rayTrans.Position1Ray, posHit); for (int i = rayHits.Count - 1; i >= 0; i--) { - if (rayHits[i].PartId == rayTrans.PartId && Math.Abs(rayHits[i].Distance - distance) < rayTrans.Tolerance2) + if (rayHits[i].PartId != rayTrans.PartId) + break; + if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay) return; } @@ -14468,76 +14512,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Helper to find ray hit in a Tri (triangle). + /// Helper to find ray hit in triangle /// - private bool HitRayInTri(Tri triangle, RayTrans rayTrans, out float distance, out Vector3 posHit, out Vector3 normal) + bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj) { - // Initialize - distance = 0.0f; - posHit = Vector3.Zero; - normal = Vector3.Zero; - float tol = rayTrans.Tolerance; - - // Project triangle on X-Y plane - Vector3 pos1 = triangle.p1 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj; - Vector3 pos2 = triangle.p2 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj; - Vector3 pos3 = triangle.p3 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj; - - // Check if ray/origo inside triangle bounding rectangle - Vector3 lower = Vector3.Min(pos1, Vector3.Min(pos2, pos3)); - Vector3 upper = Vector3.Max(pos1, Vector3.Max(pos2, pos3)); - if (lower.X > tol || lower.Y > tol || lower.Z > tol || upper.X < -tol || upper.Y < -tol || upper.Z < -rayTrans.RayLength - tol) - return false; + float tol = m_floatToleranceInCastRay; + posHitProj = Vector3.Zero; + + // Calculate triangle edge vectors + Vector3 vec1Proj = triProj.p2 - triProj.p1; + Vector3 vec2Proj = triProj.p3 - triProj.p2; + Vector3 vec3Proj = triProj.p1 - triProj.p3; - // Check if ray/origo inside every edge or reverse "outside" every edge on exit - float dist; - bool inside = true; - bool outside = true; - Vector3 vec1 = pos2 - pos1; - dist = pos1.X * vec1.Y - pos1.Y * vec1.X; - if (dist < -tol) - inside = false; - if (dist > tol) - outside = false; - Vector3 vec2 = pos3 - pos2; - dist = pos2.X * vec2.Y - pos2.Y * vec2.X; - if (dist < -tol) - inside = false; - if (dist > tol) - outside = false; - Vector3 vec3 = pos1 - pos3; - dist = pos3.X * vec3.Y - pos3.Y * vec3.X; - if (dist < -tol) - inside = false; - if (dist > tol) - outside = false; - - // Skip if ray/origo outside - if (!inside && !(outside && m_detectExitsInCastRay)) + // Calculate triangle normal + normalProj = Vector3.Cross(vec1Proj, vec2Proj); + + // Skip if degenerate triangle or ray parallell with triangle plane + float divisor = Vector3.Dot(vecRayProj, normalProj); + if (Math.Abs(divisor) < tol) return false; - // Calculate normal - Vector3 normalProj = Vector3.Cross(vec1, vec2); - float normalLength = normalProj.Length(); - // Skip if degenerate triangle - if (normalLength < tol) + // Skip if exit and not configured to detect + if (divisor > tol && !m_detectExitsInCastRay) return false; - normalProj = normalProj / normalLength; - // Skip if ray parallell to triangle plane - if (Math.Abs(normalProj.Z) < tol) + + // Skip if outside ray ends + float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor; + if (distanceProj < -tol || distanceProj > 1 + tol) return false; - // Calculate distance - distance = Vector3.Dot(normalProj, pos2) / normalProj.Z * -1.0f; - // Skip if outside ray - if (distance < -tol || distance > rayTrans.RayLength + tol) + // Calculate hit position in triangle + posHitProj = pos1RayProj + vecRayProj * distanceProj; + + // Skip if outside triangle bounding box + Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3); + Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3); + if ( + posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol || + posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol + ) return false; - // Calculate projected hit position - Vector3 posHitProj = new Vector3(0.0f, 0.0f, -distance); - // Project hit back to normal coordinate system - posHit = posHitProj * rayTrans.RotationBack - rayTrans.PositionProj; - normal = normalProj * rayTrans.RotationBack; + // Skip if outside triangle + if ( + Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol || + Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol || + Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol + ) + return false; + + // Return hit return true; } @@ -14660,24 +14684,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api y = Util.Clamp(yInt+1, 0, World.Heightmap.Height - 1); Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]); // Adjust bounding box - zLower = Math.Min(zLower, pos1.Z); - zUpper = Math.Max(zUpper, pos1.Z); + zLower = Math.Min(zLower, pos2.Z); + zUpper = Math.Max(zUpper, pos2.Z); // Corner 3 of 1x1 rectangle x = Util.Clamp(xInt, 0, World.Heightmap.Width - 1); y = Util.Clamp(yInt, 0, World.Heightmap.Height - 1); Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]); // Adjust bounding box - zLower = Math.Min(zLower, pos1.Z); - zUpper = Math.Max(zUpper, pos1.Z); + zLower = Math.Min(zLower, pos3.Z); + zUpper = Math.Max(zUpper, pos3.Z); // Corner 4 of 1x1 rectangle x = Util.Clamp(xInt+1, 0, World.Heightmap.Width - 1); y = Util.Clamp(yInt, 0, World.Heightmap.Height - 1); Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]); // Adjust bounding box - zLower = Math.Min(zLower, pos1.Z); - zUpper = Math.Max(zUpper, pos1.Z); + zLower = Math.Min(zLower, pos4.Z); + zUpper = Math.Max(zUpper, pos4.Z); // Add triangle 1 Tri triangle1 = new Tri(); @@ -14695,25 +14719,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Helper to check if a ray intersects bounding shapes. - /// - private bool InBoundingShapes(Vector3 ray, float rayLength, Vector3 scale, Vector3 posPartRel, Vector3 posPartProj, Quaternion rotProj) - { - float tol = m_floatToleranceInCastRay; - - // Check if ray intersects projected bounding box - Vector3 lowerBox = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); - Vector3 upperBox = new Vector3(float.MinValue, float.MinValue, float.MinValue); - int dummy = 0; - AddBoundingBoxOfSimpleBox(scale * -0.5f, scale * 0.5f, posPartProj, rotProj, true, ref lowerBox, ref upperBox, ref dummy); - if (lowerBox.X > tol || lowerBox.Y > tol || lowerBox.Z > tol || upperBox.X < -tol || upperBox.Y < -tol || upperBox.Z < -rayLength - tol) - return false; - - // Passed bounding shape filters, so return true - return true; - } - - /// /// Helper to get link number for a UUID. /// private int UUID2LinkNumber(SceneObjectPart part, UUID id) diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 275c207..2c17022 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1397,11 +1397,6 @@ ; Maximum number of external urls that scripts can set up in this simulator (e.g. via llRequestURL()) max_external_urls_per_simulator = 100 - ; Use version 1 of llCastRay as default if true. If set to false, the new - ; version of llCastRay will be used. This gives better accuracy but - ; uses more CPU and may may be slow on some servers - UseLlCastRayV1 = true - ; Use size boxes instead of meshed prims, sculpts and mesh when calculating bounding boxes. ; Speeds up calculations but can make them inaccurate, in some cases very inaccurate. UseSimpleBoxesInGetBoundingBox = false @@ -1494,32 +1489,52 @@ ; Worst case is twisted tube, 0.5+sqrt(1.25) PrimBoundingBoxSafetyCoefficientZ = 1.618034 - ; Accepted calculation precision error in calculations in llCastRay + ; Use llCastRay V3 if true + ; Gives better accuracy and can be faster on some servers, but slower on others, + ; compared to previous version of llCastRay + ; Generates geometry meshes and can therefore use much system resources + UseLlCastRayV3 = false + + ; Accepted calculation precision error in calculations in llCastRay V3 FloatToleranceInLlCastRay = 0.000001 - ; Accepted distance difference between duplicate hits in llCastRay + ; Accepted distance difference between duplicate hits in llCastRay V3 FloatTolerance2InLlCastRay = 0.0001 - ; Maximum number of returned hits from llCastRay + ; Detail level when rendering prims in llCastRay V3 + ; 0 = Low, 1 = Medium, 2 = High, 3 = Highest, higer level gives better accuracy but slower call + PrimDetailLevelInLlCastRay = 1 + + ; Detail level when rendering sculpts in llCastRay V3 + ; 0 = Low, 1 = Medium, 2 = High, 3 = Highest, higer level gives better accuracy but slower call + SculptDetailLevelInLlCastRay = 1 + + ; Detail level when rendering meshes in llCastRay V3 + ; 0 = Low, 1 = Medium, 2 = High, 3 = Highest, higer level gives better accuracy but slower call + MeshDetailLevelInLlCastRay = 3 + + ; Detail level when rendering avatar capsules in llCastRay V3 + ; 0 = Low, 1 = Medium, 2 = High, 3 = Highest, higer level gives better accuracy but slower call + AvatarDetailLevelInLlCastRay = 1 + + ; Maximum number of returned hits from llCastRay V3 MaxHitsInLlCastRay = 16 - ; Maximum number of returned hits per prim from llCastRay + ; Maximum number of returned hits per prim from llCastRay V3 MaxHitsPerPrimInLlCastRay = 16 - ; Maximum number of returned hits per object from llCastRay + ; Maximum number of returned hits per object from llCastRay V3 MaxHitsPerObjectInLlCastRay = 16 - ; Report ray intersections with surfaces on exits from a prim as hits in llCastRay if true + ; Report ray intersections with surfaces on exits from a prim as hits in llCastRay V3 if true DetectExitHitsInLlCastRay = false - ; Filter on parts instead of groups in llCastRay if true + ; Filter on parts instead of groups in llCastRay V3 if true FilterPartsInLlCastRay = false - ; Detect attachments in llCastRay if true + ; Detect attachments in llCastRay V3 if true DoAttachmentsInLlCastRay = false - ; Use legacy version 1 of llCastRay if true - UseLlCastRayV1 = true [DataSnapshot] ; The following set of configs pertains to search. @@ -1547,6 +1562,7 @@ ; data service ;DATA_SRV_MISearch = "http://metaverseink.com/cgi-bin/register.py" + [Economy] ; These economy values get used in the BetaGridLikeMoneyModule. - This module is for demonstration only - ; The default economy module only implements just enough to allow free actions (transfer of objects, etc). -- cgit v1.1 From 7566d22a1866402cf5a29cd70fabc0f834977d3a Mon Sep 17 00:00:00 2001 From: dahlia Date: Tue, 12 May 2015 22:54:53 -0700 Subject: update libomv to 6b8afb2b61d3 --- bin/OpenMetaverse.Rendering.Meshmerizer.dll | Bin 20480 -> 20480 bytes bin/OpenMetaverse.StructuredData.XML | 80 +- bin/OpenMetaverse.StructuredData.dll | Bin 106496 -> 106496 bytes bin/OpenMetaverse.XML | 49370 ++++++++++++++++---------- bin/OpenMetaverse.dll | Bin 2428928 -> 2244608 bytes bin/OpenMetaverseTypes.XML | 3394 +- bin/OpenMetaverseTypes.dll | Bin 110592 -> 110592 bytes 7 files changed, 31412 insertions(+), 21432 deletions(-) diff --git a/bin/OpenMetaverse.Rendering.Meshmerizer.dll b/bin/OpenMetaverse.Rendering.Meshmerizer.dll index a7bf094..8a72dc3 100755 Binary files a/bin/OpenMetaverse.Rendering.Meshmerizer.dll and b/bin/OpenMetaverse.Rendering.Meshmerizer.dll differ diff --git a/bin/OpenMetaverse.StructuredData.XML b/bin/OpenMetaverse.StructuredData.XML index 789ad5b..8f0dd81 100644 --- a/bin/OpenMetaverse.StructuredData.XML +++ b/bin/OpenMetaverse.StructuredData.XML @@ -227,122 +227,122 @@ - + - + - + - + - + - + - + - + - + - + + - + - - + + + + - + - - + + - + - + + - + - + - + - + - + - + - + - + - + - - + - + - - - - + + - + - - + + - + - - + diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll index c5f0c0e..39f439e 100755 Binary files a/bin/OpenMetaverse.StructuredData.dll and b/bin/OpenMetaverse.StructuredData.dll differ diff --git a/bin/OpenMetaverse.XML b/bin/OpenMetaverse.XML index e9a00c6..36e5b92 100644 --- a/bin/OpenMetaverse.XML +++ b/bin/OpenMetaverse.XML @@ -4,26257 +4,36237 @@ OpenMetaverse - + - Sent to the client to indicate a teleport request has completed + Permission request flags, asked when a script wants to control an Avatar - - - Interface requirements for Messaging system - + + Placeholder for empty values, shouldn't ever see this - - The of the agent + + Script wants ability to take money from you - - + + Script wants to take camera controls for you - - The simulators handle the agent teleported to + + Script wants to remap avatars controls - - A Uri which contains a list of Capabilities the simulator supports + + Script wants to trigger avatar animations + This function is not implemented on the grid - - Indicates the level of access required - to access the simulator, or the content rating, or the simulators - map status + + Script wants to attach or detach the prim or primset to your avatar - - The IP Address of the simulator + + Script wants permission to release ownership + This function is not implemented on the grid + The concept of "public" objects does not exist anymore. - - The UDP Port the simulator will listen for UDP traffic on + + Script wants ability to link/delink with other prims - - Status flags indicating the state of the Agent upon arrival, Flying, etc. + + Script wants permission to change joints + This function is not implemented on the grid - - - Serialize the object - - An containing the objects data + + Script wants permissions to change permissions + This function is not implemented on the grid - - - Deserialize the message - - An containing the data + + Script wants to track avatars camera position and rotation - - - Sent to the viewer when a neighboring simulator is requesting the agent make a connection to it. - + + Script wants to control your camera - - - Serialize the object - - An containing the objects data + + Script wants the ability to teleport you - + - Deserialize the message + Special commands used in Instant Messages - An containing the data - - - Serialize the object - - An containing the objects data + + Indicates a regular IM from another agent - - - Deserialize the message - - An containing the data + + Simple notification box with an OK button - - - Serialize the object - - An containing the objects data + + You've been invited to join a group. - - - Deserialize the message - - An containing the data + + Inventory offer - - - A message sent to the client which indicates a teleport request has failed - and contains some information on why it failed - + + Accepted inventory offer - - + + Declined inventory offer - - A string key of the reason the teleport failed e.g. CouldntTPCloser - Which could be used to look up a value in a dictionary or enum + + Group vote - - The of the Agent + + An object is offering its inventory - - A string human readable message containing the reason - An example: Could not teleport closer to destination + + Accept an inventory offer from an object - - - Serialize the object - - An containing the objects data + + Decline an inventory offer from an object - - - Deserialize the message - - An containing the data + + Unknown - - - Serialize the object - - An containing the objects data + + Start a session, or add users to a session - - - Deserialize the message - - An containing the data + + Start a session, but don't prune offline users - - - Contains a list of prim owner information for a specific parcel in a simulator - - - A Simulator will always return at least 1 entry - If agent does not have proper permission the OwnerID will be UUID.Zero - If agent does not have proper permission OR there are no primitives on parcel - the DataBlocksExtended map will not be sent from the simulator - + + Start a session with your group - - An Array of objects + + Start a session without a calling card (finder or objects) - - - Serialize the object - - An containing the objects data + + Send a message to a session - - - Deserialize the message - - An containing the data + + Leave a session - - - Prim ownership information for a specified owner on a single parcel - + + Indicates that the IM is from an object - - The of the prim owner, - UUID.Zero if agent has no permission to view prim owner information + + Sent an IM to a busy user, this is the auto response - - The total number of prims + + Shows the message in the console and chat history - - True if the OwnerID is a + + Send a teleport lure - - True if the owner is online - This is no longer used by the LL Simulators + + Response sent to the agent which inititiated a teleport invitation - - The date the most recent prim was rezzed + + Response sent to the agent which inititiated a teleport invitation - - - The details of a single parcel in a region, also contains some regionwide globals - + + Only useful if you have Linden permissions - - Simulator-local ID of this parcel + + Request a teleport lure - - Maximum corner of the axis-aligned bounding box for this - parcel + + IM to tell the user to go to an URL - - Minimum corner of the axis-aligned bounding box for this - parcel + + IM for help - - Total parcel land area + + IM sent automatically on call for help, sends a lure + to each Helper reached - - + + Like an IM but won't go to email - - Key of authorized buyer + + IM from a group officer to all group members - - Bitmap describing land layout in 4x4m squares across the - entire region + + Unknown - - + + Unknown - - Date land was claimed + + Accept a group invitation - - Appears to always be zero + + Decline a group invitation - - Parcel Description + + Unknown - - + + An avatar is offering you friendship - - + + An avatar has accepted your friendship offer - - Total number of primitives owned by the parcel group on - this parcel + + An avatar has declined your friendship offer - - Whether the land is deeded to a group or not + + Indicates that a user has started typing - - + + Indicates that a user has stopped typing - - Maximum number of primitives this parcel supports + + + Flag in Instant Messages, whether the IM should be delivered to + offline avatars as well + - - The Asset UUID of the Texture which when applied to a - primitive will display the media + + Only deliver to online avatars - - A URL which points to any Quicktime supported media type + + If the avatar is offline the message will be held until + they login next, and possibly forwarded to their e-mail account - - A byte, if 0x1 viewer should auto scale media to fit object + + + Conversion type to denote Chat Packet types in an easier-to-understand format + - - URL For Music Stream + + Whisper (5m radius) - - Parcel Name + + Normal chat (10/20m radius), what the official viewer typically sends - - Autoreturn value in minutes for others' objects + + Shouting! (100m radius) - - + + Event message when an Avatar has begun to type - - Total number of other primitives on this parcel + + Event message when an Avatar has stopped typing - - UUID of the owner of this parcel + + Send the message to the debug channel - - Total number of primitives owned by the parcel owner on - this parcel + + Event message when an object uses llOwnerSay - - + + Special value to support llRegionSay, never sent to the client - - How long is pass valid for + + + Identifies the source of a chat message + - - Price for a temporary pass + + Chat from the grid or simulator - - + + Chat from another avatar - - Disallows people outside the parcel from being able to see in + + Chat from an object - - + + + + - + - + - - True if the region denies access to age unverified users - - + - - This field is no longer used - - - The result of a request for parcel properties - - - Sale price of the parcel, only useful if ForSale is set - The SalePrice will remain the same after an ownership - transfer (sale), so it can be used to see the purchase price after - a sale if the new owner has not changed it - - + - Number of primitives your avatar is currently - selecting and sitting on in this parcel + Effect type used in ViewerEffect packets - + - - - A number which increments by 1, starting at 0 for each ParcelProperties request. - Can be overriden by specifying the sequenceID with the ParcelPropertiesRequest being sent. - a Negative number indicates the action in has occurred. - + + - - Maximum primitives across the entire simulator + + - - Total primitives across the entire simulator + + - + - - Key of parcel snapshot + + - - Parcel ownership status + + - - Total number of primitives on this parcel + + Project a beam from a source to a destination, such as + the one used when editing an object - + - + - - A description of the media - - - An Integer which represents the height of the media + + - - An integer which represents the width of the media + + Create a swirl of particles around an object - - A boolean, if true the viewer should loop the media + + - - A string which contains the mime type of the media + + - - true to obscure (hide) media url + + Cause an avatar to look at an object - - true to obscure (hide) music url + + Cause an avatar to point at an object - + - Serialize the object + The action an avatar is doing when looking at something, used in + ViewerEffect packets for the LookAt effect - An containing the objects data - - - Deserialize the message - - An containing the data + + - - A message sent from the viewer to the simulator to updated a specific parcels settings + + - - The of the agent authorized to purchase this - parcel of land or a NULL if the sale is authorized to anyone + + - - true to enable auto scaling of the parcel media + + - - The category of this parcel used when search is enabled to restrict - search results + + - - A string containing the description to set + + - - The of the which allows for additional - powers and restrictions. + + Deprecated - - The which specifies how avatars which teleport - to this parcel are handled + + - - The LocalID of the parcel to update settings on + + - - A string containing the description of the media which can be played - to visitors + + - + - + + + The action an avatar is doing when pointing at something, used in + ViewerEffect packets for the PointAt effect + + + - + - + - + - + + + Money transaction types + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - Deserialize the message - - An containing the data + + - - - Serialize the object - - An containing the objects data + + - - Base class used for the RemoteParcelRequest message + + - - - A message sent from the viewer to the simulator to request information - on a remote parcel - + + - - Local sim position of the parcel we are looking up + + - - Region handle of the parcel we are looking up + + - - Region of the parcel we are looking up + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - A message sent from the simulator to the viewer in response to a - which will contain parcel information - + + - - The grid-wide unique parcel ID + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - A message containing a request for a remote parcel from a viewer, or a response - from the simulator to that request - + + - - The request or response details block + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - A message sent from the simulator to an agent which contains - the groups the agent is in - + + - - The Agent receiving the message + + - - An array containing information - for each the agent is a member of + + - - An array containing information - for each the agent is a member of + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - Group Details specific to the agent + + - - true of the agent accepts group notices + + - - The agents tier contribution to the group + + - - The Groups + + - - The of the groups insignia + + - - The name of the group + + - - The aggregate permissions the agent has in the group for all roles the agent - is assigned + + - - An optional block containing additional agent specific information + + - - true of the agent allows this group to be - listed in their profile + + - + + + + - A message sent from the viewer to the simulator which - specifies the language and permissions for others to detect - the language specified + - - A string containng the default language - to use for the agent + + - - true of others are allowed to - know the language setting + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - An EventQueue message sent from the simulator to an agent when the agent - leaves a group - + + - - - An Array containing the AgentID and GroupID - + + - + - Serialize the object + - An containing the objects data - - - Deserialize the message - - An containing the data + + - - An object containing the Agents UUID, and the Groups UUID + + - - The ID of the Agent leaving the group + + - - The GroupID the Agent is leaving + + - - Base class for Asset uploads/results via Capabilities + + - - - The request state - + + - + - Serialize the object + Flags sent when a script takes or releases a control - An containing the objects data + NOTE: (need to verify) These might be a subset of the ControlFlags enum in Movement, - - - Deserialize the message - - An containing the data + + No Flags set - - - A message sent from the viewer to the simulator to request a temporary upload capability - which allows an asset to be uploaded - + + Forward (W or up Arrow) - - The Capability URL sent by the simulator to upload the baked texture to + + Back (S or down arrow) - - - A message sent from the simulator that will inform the agent the upload is complete, - and the UUID of the uploaded asset - + + Move left (shift+A or left arrow) - - The uploaded texture asset ID + + Move right (shift+D or right arrow) - - - A message sent from the viewer to the simulator to request a temporary - capability URI which is used to upload an agents baked appearance textures - + + Up (E or PgUp) - - Object containing request or response + + Down (C or PgDown) - - - Serialize the object - - An containing the objects data + + Rotate left (A or left arrow) - - - Deserialize the message - - An containing the data + + Rotate right (D or right arrow) - + + Left Mouse Button + + + Left Mouse button in MouseLook + + - A message sent from the simulator which indicates the minimum version required for - using voice chat + Currently only used to hide your group title - - Major Version Required - - - Minor version required + + No flags set - - The name of the region sending the version requrements + + Hide your group title - + - Serialize the object + Action state of the avatar, which can currently be typing and + editing - An containing the objects data - - - Deserialize the message - - An containing the data + + - + + + + + + + - A message sent from the simulator to the viewer containing the - voice server URI + Current teleport status - - The Parcel ID which the voice server URI applies + + Unknown status - - The name of the region + + Teleport initialized - - A uri containing the server/channel information - which the viewer can utilize to participate in voice conversations + + Teleport in progress - - - Serialize the object - - An containing the objects data + + Teleport failed - - - Deserialize the message - - An containing the data + + Teleport completed - + + Teleport cancelled + + - - + + No flags set, or teleport failed - + + Set when newbie leaves help island for first time + + - - - Serialize the object - - An containing the objects data + + Via Lure - - - Deserialize the message - - An containing the data + + Via Landmark - - - A message sent by the viewer to the simulator to request a temporary - capability for a script contained with in a Tasks inventory to be updated - + + Via Location - - Object containing request or response + + Via Home - - - Serialize the object - - An containing the objects data + + Via Telehub - - - Deserialize the message - - An containing the data + + Via Login - - - A message sent from the simulator to the viewer to indicate - a Tasks scripts status. - + + Linden Summoned - - The Asset ID of the script + + Linden Forced me - - True of the script is compiled/ran using the mono interpreter, false indicates it - uses the older less efficient lsl2 interprter + + - - The Task containing the scripts + + Agent Teleported Home via Script - - true of the script is in a running state + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - A message containing the request/response used for updating a gesture - contained with an agents inventory - + + forced to new location for example when avatar is banned or ejected - - Object containing request or response + + Teleport Finished via a Lure - - - Serialize the object - - An containing the objects data + + Finished, Sim Changed - - - Deserialize the message - - An containing the data + + Finished, Same Sim - + - A message request/response which is used to update a notecard contained within - a tasks inventory + - - The of the Task containing the notecard asset to update + + - - The notecard assets contained in the tasks inventory + + - - - Serialize the object - - An containing the objects data + + - + - Deserialize the message + - An containing the data - - - A reusable class containing a message sent from the viewer to the simulator to request a temporary uploader capability - which is used to update an asset in an agents inventory - + + - - - The Notecard AssetID to replace - + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - + - A message containing the request/response used for updating a notecard - contained with an agents inventory + Type of mute entry - - Object containing request or response + + Object muted by name - - - Serialize the object - - An containing the objects data + + Muted residet - - - Deserialize the message - - An containing the data + + Object muted by UUID - - - Serialize the object - - An containing the objects data + + Muted group - - - Deserialize the message - - An containing the data + + Muted external entry - + - A message sent from the simulator to the viewer which indicates - an error occurred while attempting to update a script in an agents or tasks - inventory + Flags of mute entry - - true of the script was successfully compiled by the simulator - - - A string containing the error which occured while trying - to update the script - - - A new AssetID assigned to the script - - - - A message sent from the viewer to the simulator - requesting the update of an existing script contained - within a tasks inventory - + + No exceptions - - if true, set the script mode to running + + Don't mute text chat - - The scripts InventoryItem ItemID to update + + Don't mute voice chat - - A lowercase string containing either "mono" or "lsl2" which - specifies the script is compiled and ran on the mono runtime, or the older - lsl runtime + + Don't mute particles - - The tasks which contains the script to update + + Don't mute sounds - - - Serialize the object - - An containing the objects data + + Don't mute - + - Deserialize the message + Instant Message - An containing the data - - - A message containing either the request or response used in updating a script inside - a tasks inventory - + + Key of sender - - Object containing request or response + + Name of sender - - - Serialize the object - - An containing the objects data + + Key of destination avatar - - - Deserialize the message - - An containing the data + + ID of originating estate - - - Response from the simulator to notify the viewer the upload is completed, and - the UUID of the script asset and its compiled status - + + Key of originating region - - The uploaded texture asset ID + + Coordinates in originating region - - true of the script was compiled successfully + + Instant message type - - - A message sent from a viewer to the simulator requesting a temporary uploader capability - used to update a script contained in an agents inventory - + + Group IM session toggle - - The existing asset if of the script in the agents inventory to replace + + Key of IM session, for Group Messages, the groups UUID - - The language of the script - Defaults to lsl version 2, "mono" might be another possible option + + Timestamp of the instant message - - - Serialize the object - - An containing the objects data + + Instant message text - - - Deserialize the message - - An containing the data + + Whether this message is held for offline avatars - - - A message containing either the request or response used in updating a script inside - an agents inventory - + + Context specific packed data - - Object containing request or response + + Print the struct data as a string + A string containing the field name, and field value - - - Serialize the object - - An containing the objects data + + Represents muted object or resident - - - Deserialize the message - - An containing the data + + Type of the mute entry - - - Serialize the object - - An containing the objects data + + UUID of the mute etnry - - - Deserialize the message - - An containing the data + + Mute entry name - - Base class for Map Layers via Capabilities + + Mute flags - - + + Transaction detail sent with MoneyBalanceReply message - - - Serialize the object - - An containing the objects data + + Type of the transaction - - - Deserialize the message - - An containing the data + + UUID of the transaction source - - - Sent by an agent to the capabilities server to request map layers - + + Is the transaction source a group - - - A message sent from the simulator to the viewer which contains an array of map images and their grid coordinates - + + UUID of the transaction destination - - An array containing LayerData items + + Is transaction destination a group - - - Serialize the object - - An containing the objects data + + Transaction amount - - - Deserialize the message - - An containing the data + + Transaction description - + - An object containing map location details + Manager class for our own avatar - - The Asset ID of the regions tile overlay + + The event subscribers. null if no subcribers - - The grid location of the southern border of the map tile + + Raises the ChatFromSimulator event + A ChatEventArgs object containing the + data returned from the data server - - The grid location of the western border of the map tile + + Thread sync lock object - - The grid location of the eastern border of the map tile + + The event subscribers. null if no subcribers - - The grid location of the northern border of the map tile + + Raises the ScriptDialog event + A SctriptDialogEventArgs object containing the + data returned from the data server - - Object containing request or response + + Thread sync lock object - - - Serialize the object - - An containing the objects data + + The event subscribers. null if no subcribers - - - Deserialize the message - - An containing the data + + Raises the ScriptQuestion event + A ScriptQuestionEventArgs object containing the + data returned from the data server - - - New as of 1.23 RC1, no details yet. - + + Thread sync lock object - - - Serialize the object - - An containing the objects data + + The event subscribers. null if no subcribers - - - Deserialize the message - - An containing the data + + Raises the LoadURL event + A LoadUrlEventArgs object containing the + data returned from the data server - - - Serialize the object - - An containing the objects data + + Thread sync lock object - - - Deserialize the message - - An containing the data + + The event subscribers. null if no subcribers - - A string containing the method used + + Raises the MoneyBalance event + A BalanceEventArgs object containing the + data returned from the data server - - - A request sent from an agent to the Simulator to begin a new conference. - Contains a list of Agents which will be included in the conference - + + Thread sync lock object - - An array containing the of the agents invited to this conference + + The event subscribers. null if no subcribers - - The conferences Session ID + + Raises the MoneyBalanceReply event + A MoneyBalanceReplyEventArgs object containing the + data returned from the data server - - - Serialize the object - - An containing the objects data + + Thread sync lock object - - - Deserialize the message - - An containing the data + + The event subscribers. null if no subcribers - - - A moderation request sent from a conference moderator - Contains an agent and an optional action to take - + + Raises the IM event + A InstantMessageEventArgs object containing the + data returned from the data server - - The Session ID + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - A list containing Key/Value pairs, known valid values: - key: text value: true/false - allow/disallow specified agents ability to use text in session - key: voice value: true/false - allow/disallow specified agents ability to use voice in session - - "text" or "voice" + + Raises the TeleportProgress event + A TeleportEventArgs object containing the + data returned from the data server - - + + Thread sync lock object - - - Serialize the object - - An containing the objects data + + The event subscribers. null if no subcribers - - - Deserialize the message - - An containing the data + + Raises the AgentDataReply event + A AgentDataReplyEventArgs object containing the + data returned from the data server - - - A message sent from the agent to the simulator which tells the - simulator we've accepted a conference invitation - + + Thread sync lock object - - The conference SessionID + + The event subscribers. null if no subcribers - - - Serialize the object - - An containing the objects data + + Raises the AnimationsChanged event + A AnimationsChangedEventArgs object containing the + data returned from the data server - - - Deserialize the message - - An containing the data + + Thread sync lock object - - - Serialize the object - - An containing the objects data + + The event subscribers. null if no subcribers - - - Deserialize the message - - An containing the data + + Raises the MeanCollision event + A MeanCollisionEventArgs object containing the + data returned from the data server - - - Serialize the object - - An containing the objects data + + Thread sync lock object - - - Deserialize the message - - An containing the data + + The event subscribers. null if no subcribers - - - Serialize the object - - An containing the objects data + + Raises the RegionCrossed event + A RegionCrossedEventArgs object containing the + data returned from the data server - - - Deserialize the message - - An containing the data + + Thread sync lock object - - Key of sender + + The event subscribers. null if no subcribers - - Name of sender + + Raises the GroupChatJoined event + A GroupChatJoinedEventArgs object containing the + data returned from the data server - - Key of destination avatar + + Thread sync lock object - - ID of originating estate + + The event subscribers. null if no subcribers - - Key of originating region + + Raises the AlertMessage event + A AlertMessageEventArgs object containing the + data returned from the data server - - Coordinates in originating region + + Thread sync lock object - - Instant message type + + The event subscribers. null if no subcribers - - Group IM session toggle + + Raises the ScriptControlChange event + A ScriptControlEventArgs object containing the + data returned from the data server - - Key of IM session, for Group Messages, the groups UUID + + Thread sync lock object - - Timestamp of the instant message + + The event subscribers. null if no subcribers - - Instant message text + + Raises the CameraConstraint event + A CameraConstraintEventArgs object containing the + data returned from the data server - - Whether this message is held for offline avatars + + Thread sync lock object - - Context specific packed data + + The event subscribers. null if no subcribers - - Is this invitation for voice group/conference chat + + Raises the ScriptSensorReply event + A ScriptSensorReplyEventArgs object containing the + data returned from the data server - - - Serialize the object - - An containing the objects data + + Thread sync lock object - - - Deserialize the message - - An containing the data + + The event subscribers. null if no subcribers - - - Sent from the simulator to the viewer. - - When an agent initially joins a session the AgentUpdatesBlock object will contain a list of session members including - a boolean indicating they can use voice chat in this session, a boolean indicating they are allowed to moderate - this session, and lastly a string which indicates another agent is entering the session with the Transition set to "ENTER" - - During the session lifetime updates on individuals are sent. During the update the booleans sent during the initial join are - excluded with the exception of the Transition field. This indicates a new user entering or exiting the session with - the string "ENTER" or "LEAVE" respectively. - + + Raises the AvatarSitResponse event + A AvatarSitResponseEventArgs object containing the + data returned from the data server - - - Serialize the object - - An containing the objects data + + Thread sync lock object - - - Deserialize the message - - An containing the data + + The event subscribers. null if no subcribers - - - An EventQueue message sent when the agent is forcibly removed from a chatterbox session - + + Raises the ChatSessionMemberAdded event + A ChatSessionMemberAddedEventArgs object containing the + data returned from the data server - - - A string containing the reason the agent was removed - + + Thread sync lock object - - - The ChatterBoxSession's SessionID - + + The event subscribers. null if no subcribers - - - Serialize the object - - An containing the objects data + + Raises the ChatSessionMemberLeft event + A ChatSessionMemberLeftEventArgs object containing the + data returned from the data server - - - Deserialize the message - - An containing the data + + Thread sync lock object - - - Serialize the object - - An containing the objects data + + The event subscribers, null of no subscribers - - - Deserialize the message - - An containing the data + + Raises the SetDisplayNameReply Event + A SetDisplayNameReplyEventArgs object containing + the data sent from the simulator - - - Serialize the object - - An containing the objects data + + Thread sync lock object - - - Deserialize the message - - An containing the data + + The event subscribers. null if no subcribers - + + Raises the MuteListUpdated event + A EventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + Reference to the GridClient instance + + + Used for movement and camera tracking + + + Currently playing animations for the agent. Can be used to + check the current movement status such as walking, hovering, aiming, + etc. by checking against system animations found in the Animations class + + + Dictionary containing current Group Chat sessions and members + + + Dictionary containing mute list keyead on mute name and key + + + Various abilities and preferences sent by the grid + + - Serialize the object + Constructor, setup callbacks for packets related to our avatar - An containing the objects data + A reference to the Class - + - Deserialize the message + Send a text message from the Agent to the Simulator - An containing the data + A containing the message + The channel to send the message on, 0 is the public channel. Channels above 0 + can be used however only scripts listening on the specified channel will see the message + Denotes the type of message being sent, shout, whisper, etc. - + - Serialize the object + Request any instant messages sent while the client was offline to be resent. - An containing the objects data - + - Deserialize the message + Send an Instant Message to another Avatar - An containing the data + The recipients + A containing the message to send - + - + Send an Instant Message to an existing group chat or conference chat + The recipients + A containing the message to send + IM session ID (to differentiate between IM windows) - + - Serialize the object + Send an Instant Message - An containing the objects data + The name this IM will show up as being from + Key of Avatar + Text message being sent + IM session ID (to differentiate between IM windows) + IDs of sessions for a conference - + - Deserialize the message + Send an Instant Message - An containing the data + The name this IM will show up as being from + Key of Avatar + Text message being sent + IM session ID (to differentiate between IM windows) + Type of instant message to send + Whether to IM offline avatars as well + Senders Position + RegionID Sender is In + Packed binary data that is specific to + the dialog type - + - Serialize the object + Send an Instant Message to a group - An containing the objects data + of the group to send message to + Text Message being sent. - + - Deserialize the message + Send an Instant Message to a group the agent is a member of - An containing the data + The name this IM will show up as being from + of the group to send message to + Text message being sent - + - Serialize the object + Send a request to join a group chat session - An containing the objects data + of Group to leave - + - Deserialize the message + Exit a group chat session. This will stop further Group chat messages + from being sent until session is rejoined. - An containing the data + of Group chat session to leave - + - Event Queue message describing physics engine attributes of a list of objects - Sim sends these when object is selected + Reply to script dialog questions. + Channel initial request came on + Index of button you're "clicking" + Label of button you're "clicking" + of Object that sent the dialog request + - - Array with the list of physics properties - - + - Serializes the message + Accept invite for to a chatterbox session - Serialized OSD + of session to accept invite to - + - Deseializes the message + Start a friends conference - Incoming data to deserialize + List of UUIDs to start a conference with + the temportary session ID returned in the callback> - + - A message sent from the viewer to the simulator which - specifies that the user has changed current URL - of the specific media on a prim face + Start a particle stream between an agent and an object + Key of the source agent + Key of the target object + + The type from the enum + A unique for this effect - + - New URL + Start a particle stream between an agent and an object + Key of the source agent + Key of the target object + A representing the beams offset from the source + A which sets the avatars lookat animation + of the Effect - + - Prim UUID where navigation occured + Create a particle beam between an avatar and an primitive + The ID of source avatar + The ID of the target primitive + global offset + A object containing the combined red, green, blue and alpha + color values of particle beam + a float representing the duration the parcicle beam will last + A Unique ID for the beam + - + - Face index + Create a particle swirl around a target position using a packet + global offset + A object containing the combined red, green, blue and alpha + color values of particle beam + a float representing the duration the parcicle beam will last + A Unique ID for the beam - + - Serialize the object + Sends a request to sit on the specified object - An containing the objects data + of the object to sit on + Sit at offset - + - Deserialize the message + Follows a call to to actually sit on the object - An containing the data - - Base class used for the ObjectMedia message + + Stands up from sitting on a prim or the ground + true of AgentUpdate was sent - + - Message used to retrive prim media data + Does a "ground sit" at the avatar's current position - + - Prim UUID + Starts or stops flying + True to start flying, false to stop flying - + - Requested operation, either GET or UPDATE + Starts or stops crouching + True to start crouching, false to stop crouching - + - Serialize object + Starts a jump (begin holding the jump key) - Serialized object as OSDMap - + - Deserialize the message + Use the autopilot sim function to move the avatar to a new + position. Uses double precision to get precise movements - An containing the data + The z value is currently not handled properly by the simulator + Global X coordinate to move to + Global Y coordinate to move to + Z coordinate to move to - + - Message used to update prim media data + Use the autopilot sim function to move the avatar to a new position + The z value is currently not handled properly by the simulator + Integer value for the global X coordinate to move to + Integer value for the global Y coordinate to move to + Floating-point value for the Z coordinate to move to - + - Prim UUID + Use the autopilot sim function to move the avatar to a new position + The z value is currently not handled properly by the simulator + Integer value for the local X coordinate to move to + Integer value for the local Y coordinate to move to + Floating-point value for the Z coordinate to move to - + + Macro to cancel autopilot sim function + Not certain if this is how it is really done + true if control flags were set and AgentUpdate was sent to the simulator + + - Array of media entries indexed by face number + Grabs an object + an unsigned integer of the objects ID within the simulator + - + - Media version string + Overload: Grab a simulated object + an unsigned integer of the objects ID within the simulator + + The texture coordinates to grab + The surface coordinates to grab + The face of the position to grab + The region coordinates of the position to grab + The surface normal of the position to grab (A normal is a vector perpindicular to the surface) + The surface binormal of the position to grab (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - + - Serialize object + Drag an object - Serialized object as OSDMap + of the object to drag + Drag target in region coordinates - + - Deserialize the message + Overload: Drag an object - An containing the data + of the object to drag + Drag target in region coordinates + + The texture coordinates to grab + The surface coordinates to grab + The face of the position to grab + The region coordinates of the position to grab + The surface normal of the position to grab (A normal is a vector perpindicular to the surface) + The surface binormal of the position to grab (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - + - Message used to update prim media data + Release a grabbed object + The Objects Simulator Local ID + + + - + - Prim UUID + Release a grabbed object + The Objects Simulator Local ID + The texture coordinates to grab + The surface coordinates to grab + The face of the position to grab + The region coordinates of the position to grab + The surface normal of the position to grab (A normal is a vector perpindicular to the surface) + The surface binormal of the position to grab (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - + - Array of media entries indexed by face number + Touches an object + an unsigned integer of the objects ID within the simulator + - + - Requested operation, either GET or UPDATE + Request the current L$ balance - + - Serialize object + Give Money to destination Avatar - Serialized object as OSDMap + UUID of the Target Avatar + Amount in L$ - + - Deserialize the message + Give Money to destination Avatar - An containing the data + UUID of the Target Avatar + Amount in L$ + Description that will show up in the + recipients transaction history - + - Message for setting or getting per face MediaEntry + Give L$ to an object + object to give money to + amount of L$ to give + name of object - - The request or response details block - - + - Serialize the object + Give L$ to a group - An containing the objects data + group to give money to + amount of L$ to give - + - Deserialize the message + Give L$ to a group - An containing the data - - - Details about object resource usage - - - Object UUID - - - Object name - - - Indicates if object is group owned - - - Locatio of the object - - - Object owner - - - Resource usage, keys are resource names, values are resource usage for that specific resource + group to give money to + amount of L$ to give + description of transaction - + - Deserializes object from OSD + Pay texture/animation upload fee - An containing the data - + - Makes an instance based on deserialized data + Pay texture/animation upload fee - serialized data - Instance containg deserialized data - - - Details about parcel resource usage - - - Parcel UUID - - - Parcel local ID - - - Parcel name - - - Indicates if parcel is group owned - - - Parcel owner - - - Array of containing per object resource usage + description of the transaction - + - Deserializes object from OSD + Give Money to destination Object or Avatar - An containing the data + UUID of the Target Object/Avatar + Amount in L$ + Reason (Optional normally) + The type of transaction + Transaction flags, mostly for identifying group + transactions - + - Makes an instance based on deserialized data + Plays a gesture - serialized data - Instance containg deserialized data - - - Resource usage base class, both agent and parcel resource - usage contains summary information - - - Summary of available resources, keys are resource names, - values are resource usage for that specific resource - - - Summary resource usage, keys are resource names, - values are resource usage for that specific resource + Asset of the gesture - + - Serializes object + Mark gesture active - serialized data + Inventory of the gesture + Asset of the gesture - + - Deserializes object from OSD + Mark gesture inactive - An containing the data - - - Agent resource usage - - - Per attachment point object resource usage + Inventory of the gesture - + - Deserializes object from OSD + Send an AgentAnimation packet that toggles a single animation on - An containing the data + The of the animation to start playing + Whether to ensure delivery of this packet or not - + - Makes an instance based on deserialized data + Send an AgentAnimation packet that toggles a single animation off - serialized data - Instance containg deserialized data + The of a + currently playing animation to stop playing + Whether to ensure delivery of this packet or not - + - Detects which class handles deserialization of this message + Send an AgentAnimation packet that will toggle animations on or off - An containing the data - Object capable of decoding this message - - - Request message for parcel resource usage - - - UUID of the parel to request resource usage info + A list of animation s, and whether to + turn that animation on or off + Whether to ensure delivery of this packet or not - + - Serializes object + Teleports agent to their stored home location - serialized data + true on successful teleport to home location - + - Deserializes object from OSD + Teleport agent to a landmark - An containing the data - - - Response message for parcel resource usage - - - URL where parcel resource usage details can be retrieved - - - URL where parcel resource usage summary can be retrieved + of the landmark to teleport agent to + true on success, false on failure - + - Serializes object + Attempt to look up a simulator name and teleport to the discovered + destination - serialized data + Region name to look up + Position to teleport to + True if the lookup and teleport were successful, otherwise + false - + - Deserializes object from OSD + Attempt to look up a simulator name and teleport to the discovered + destination - An containing the data + Region name to look up + Position to teleport to + Target to look at + True if the lookup and teleport were successful, otherwise + false - + - Detects which class handles deserialization of this message + Teleport agent to another region - An containing the data - Object capable of decoding this message - - - Parcel resource usage - - - Array of containing per percal resource usage + handle of region to teleport agent to + position in destination sim to teleport to + true on success, false on failure + This call is blocking - + - Deserializes object from OSD + Teleport agent to another region - An containing the data + handle of region to teleport agent to + position in destination sim to teleport to + direction in destination sim agent will look at + true on success, false on failure + This call is blocking - + - Reply to request for bunch if display names + Request teleport to a another simulator + handle of region to teleport agent to + position in destination sim to teleport to - - Current display name - - - Following UUIDs failed to return a valid display name - - + - Serializes the message + Request teleport to a another simulator - OSD containting the messaage + handle of region to teleport agent to + position in destination sim to teleport to + direction in destination sim agent will look at - + - Message sent when requesting change of the display name + Teleport agent to a landmark + of the landmark to teleport agent to - - Current display name - - - Desired new display name - - + - Serializes the message + Send a teleport lure to another avatar with default "Join me in ..." invitation message - OSD containting the messaage + target avatars to lure - + - Message recieved in response to request to change display name + Send a teleport lure to another avatar with custom invitation message + target avatars to lure + custom message to send with invitation - - New display name - - - String message indicating the result of the operation - - - Numerical code of the result, 200 indicates success - - + - Serializes the message + Respond to a teleport lure by either accepting it and initiating + the teleport, or denying it - OSD containting the messaage + of the avatar sending the lure + IM session of the incoming lure request + true to accept the lure, false to decline it - + - Message recieved when someone nearby changes their display name + Update agent profile + struct containing updated + profile information - - Previous display name, empty string if default - - - New display name - - + - Serializes the message + Update agents profile interests - OSD containting the messaage + selection of interests from struct - + - + Set the height and the width of the client window. This is used + by the server to build a virtual camera frustum for our avatar + New height of the viewer window + New width of the viewer window - + - Initialize the UDP packet handler in server mode + Request the list of muted objects and avatars for this agent - Port to listening for incoming UDP packets on - + - Initialize the UDP packet handler in client mode + Mute an object, resident, etc. - Remote UDP server to connect to + Mute type + Mute UUID + Mute name - + - + Mute an object, resident, etc. + Mute type + Mute UUID + Mute name + Mute flags - + - + Unmute an object, resident, etc. + Mute UUID + Mute name - + - + Sets home location to agents current position + will fire an AlertMessage () with + success or failure message - + - + Move an agent in to a simulator. This packet is the last packet + needed to complete the transition in to a new simulator + Object - - No report - - - Unknown report type - - - Bug report + + + Reply to script permissions request + + Object + of the itemID requesting permissions + of the taskID requesting permissions + list of permissions to allow - - Complaint report + + + Respond to a group invitation by either accepting or denying it + + UUID of the group (sent in the AgentID field of the invite message) + IM Session ID from the group invitation message + Accept the group invitation or deny it - - Customer service report + + + Requests script detection of objects and avatars + + name of the object/avatar to search for + UUID of the object or avatar to search for + Type of search from ScriptSensorTypeFlags + range of scan (96 max?) + the arc in radians to search within + an user generated ID to correlate replies with + Simulator to perform search in - + - Bitflag field for ObjectUpdateCompressed data blocks, describing - which options are present for each object + Create or update profile pick + UUID of the pick to update, or random UUID to create a new pick + Is this a top pick? (typically false) + UUID of the parcel (UUID.Zero for the current parcel) + Name of the pick + Global position of the pick landmark + UUID of the image displayed with the pick + Long description of the pick - - Unknown - - - Whether the object has a TreeSpecies - - - Whether the object has floating text ala llSetText - - - Whether the object has an active particle system - - - Whether the object has sound attached to it - - - Whether the object is attached to a root object or not - - - Whether the object has texture animation settings + + + Delete profile pick + + UUID of the pick to delete - - Whether the object has an angular velocity + + + Create or update profile Classified + + UUID of the classified to update, or random UUID to create a new classified + Defines what catagory the classified is in + UUID of the image displayed with the classified + Price that the classified will cost to place for a week + Global position of the classified landmark + Name of the classified + Long description of the classified + if true, auto renew classified after expiration - - Whether the object has a name value pairs string + + + Create or update profile Classified + + UUID of the classified to update, or random UUID to create a new classified + Defines what catagory the classified is in + UUID of the image displayed with the classified + Price that the classified will cost to place for a week + Name of the classified + Long description of the classified + if true, auto renew classified after expiration - - Whether the object has a Media URL set + + + Delete a classified ad + + The classified ads ID - + - Specific Flags for MultipleObjectUpdate requests + Fetches resource usage by agents attachmetns + Called when the requested information is collected - - None + + + Initates request to set a new display name + + Previous display name + Desired new display name - - Change position of prims + + + Tells the sim what UI language is used, and if it's ok to share that with scripts + + Two letter language code + Share language info with scripts - - Change rotation of prims + + + Sets agents maturity access level + + PG, M or A - - Change size of prims + + + Sets agents maturity access level + + PG, M or A + Callback function - - Perform operation on link set + + + Take an incoming ImprovedInstantMessage packet, auto-parse, and if + OnInstantMessage is defined call that with the appropriate arguments + + The sender + The EventArgs object containing the packet data - - Scale prims uniformly, same as selecing ctrl+shift in the - viewer. Used in conjunction with Scale + + + Take an incoming Chat packet, auto-parse, and if OnChat is defined call + that with the appropriate arguments. + + The sender + The EventArgs object containing the packet data - + - Special values in PayPriceReply. If the price is not one of these - literal value of the price should be use + Used for parsing llDialogs + The sender + The EventArgs object containing the packet data - + - Indicates that this pay option should be hidden + Used for parsing llRequestPermissions dialogs + The sender + The EventArgs object containing the packet data - + - Indicates that this pay option should have the default value + Handles Script Control changes when Script with permissions releases or takes a control + The sender + The EventArgs object containing the packet data - + - Contains the variables sent in an object update packet for objects. - Used to track position and movement of prims and avatars + Used for parsing llLoadURL Dialogs + The sender + The EventArgs object containing the packet data - - + + + Update client's Position, LookAt and region handle from incoming packet + + The sender + The EventArgs object containing the packet data + This occurs when after an avatar moves into a new sim - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + + EQ Message fired with the result of SetDisplayName request + + The message key + the IMessage object containing the deserialized data sent from the simulator + The which originated the packet - - + + + Process TeleportFailed message sent via EventQueue, informs agent its last teleport has failed and why. + + The Message Key + An IMessage object Deserialized from the recieved message event + The simulator originating the event message - - + + + Process TeleportFinish from Event Queue and pass it onto our TeleportHandler + + The message system key for this event + IMessage object containing decoded data from OSD + The simulator originating the event message - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - Handles all network traffic related to prims and avatar positions and - movement. + Crossed region handler for message that comes across the EventQueue. Sent to an agent + when the agent crosses a sim border into a new region. + The message key + the IMessage object containing the deserialized data sent from the simulator + The which originated the packet - - The event subscribers, null of no subscribers - - - Thread sync lock object - - - The event subscribers, null of no subscribers + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + This packet is now being sent via the EventQueue - - Raises the ObjectProperties Event - A ObjectPropertiesEventArgs object containing - the data sent from the simulator + + + Group Chat event handler + + The capability Key + IMessage object containing decoded data from OSD + - - Thread sync lock object + + + Response from request to join a group chat + + + IMessage object containing decoded data from OSD + - - The event subscribers, null of no subscribers + + + Someone joined or left group chat + + + IMessage object containing decoded data from OSD + - - Raises the ObjectPropertiesUpdated Event - A ObjectPropertiesUpdatedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object + + + Handle a group chat Invitation + + Caps Key + IMessage object containing decoded data from OSD + Originating Simulator - - The event subscribers, null of no subscribers + + + Moderate a chat session + + the of the session to moderate, for group chats this will be the groups UUID + the of the avatar to moderate + Either "voice" to moderate users voice, or "text" to moderate users text session + true to moderate (silence user), false to allow avatar to speak - - Raises the ObjectPropertiesFamily Event - A ObjectPropertiesFamilyEventArgs object containing - the data sent from the simulator + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Thread sync lock object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - The event subscribers, null of no subscribers + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Raises the AvatarUpdate Event - A AvatarUpdateEventArgs object containing - the data sent from the simulator + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Thread sync lock object + + Raised when a scripted object or agent within range sends a public message - - The event subscribers, null of no subscribers + + Raised when a scripted object sends a dialog box containing possible + options an agent can respond to - - Thread sync lock object + + Raised when an object requests a change in the permissions an agent has permitted - - The event subscribers, null of no subscribers + + Raised when a script requests an agent open the specified URL - - Raises the ObjectDataBlockUpdate Event - A ObjectDataBlockUpdateEventArgs object containing - the data sent from the simulator + + Raised when an agents currency balance is updated - - Thread sync lock object + + Raised when a transaction occurs involving currency such as a land purchase - - The event subscribers, null of no subscribers + + Raised when an ImprovedInstantMessage packet is recieved from the simulator, this is used for everything from + private messaging to friendship offers. The Dialog field defines what type of message has arrived - - Raises the KillObject Event - A KillObjectEventArgs object containing - the data sent from the simulator + + Raised when an agent has requested a teleport to another location, or when responding to a lure. Raised multiple times + for each teleport indicating the progress of the request - - Thread sync lock object + + Raised when a simulator sends agent specific information for our avatar. - - The event subscribers, null of no subscribers + + Raised when our agents animation playlist changes - - Raises the KillObjects Event - A KillObjectsEventArgs object containing - the data sent from the simulator + + Raised when an object or avatar forcefully collides with our agent - - Thread sync lock object + + Raised when our agent crosses a region border into another region - - The event subscribers, null of no subscribers + + Raised when our agent succeeds or fails to join a group chat session - - Raises the AvatarSitChanged Event - A AvatarSitChangedEventArgs object containing - the data sent from the simulator + + Raised when a simulator sends an urgent message usually indication the recent failure of + another action we have attempted to take such as an attempt to enter a parcel where we are denied access - - Thread sync lock object + + Raised when a script attempts to take or release specified controls for our agent - - The event subscribers, null of no subscribers + + Raised when the simulator detects our agent is trying to view something + beyond its limits - - Raises the PayPriceReply Event - A PayPriceReplyEventArgs object containing - the data sent from the simulator + + Raised when a script sensor reply is received from a simulator - - Thread sync lock object + + Raised in response to a request - - The event subscribers, null of no subscribers + + Raised when an avatar enters a group chat session we are participating in - - Raises the PhysicsProperties Event - A PhysicsPropertiesEventArgs object containing - the data sent from the simulator + + Raised when an agent exits a group chat session we are participating in - - Thread sync lock object + + Raised when the simulator sends us data containing + the details of display name change - - Reference to the GridClient object + + Raised when a scripted object or agent within range sends a public message - - Does periodic dead reckoning calculation to convert - velocity and acceleration to new positions for objects + + Your (client) avatars + "client", "agent", and "avatar" all represent the same thing - - - Construct a new instance of the ObjectManager class - - A reference to the instance + + Temporary assigned to this session, used for + verifying our identity in packets - - - Request information for a single object from a - you are currently connected to - - The the object is located - The Local ID of the object + + Shared secret that is never sent over the wire - - - Request information for multiple objects contained in - the same simulator - - The the objects are located - An array containing the Local IDs of the objects + + Your (client) avatar ID, local to the current region/sim - - - Attempt to purchase an original object, a copy, or the contents of - an object - - The the object is located - The Local ID of the object - Whether the original, a copy, or the object - contents are on sale. This is used for verification, if the this - sale type is not valid for the object the purchase will fail - Price of the object. This is used for - verification, if it does not match the actual price the purchase - will fail - Group ID that will be associated with the new - purchase - Inventory folder UUID where the object or objects - purchased should be placed - - - BuyObject(Client.Network.CurrentSim, 500, SaleType.Copy, - 100, UUID.Zero, Client.Self.InventoryRootFolderUUID); - - + + Where the avatar started at login. Can be "last", "home" + or a login - - - Request prices that should be displayed in pay dialog. This will triggger the simulator - to send us back a PayPriceReply which can be handled by OnPayPriceReply event - - The the object is located - The ID of the object - The result is raised in the event + + The access level of this agent, usually M, PG or A - - - Select a single object. This will cause the to send us - an which will raise the event - - The the object is located - The Local ID of the object - + + The CollisionPlane of Agent - - - Select a single object. This will cause the to send us - an which will raise the event - - The the object is located - The Local ID of the object - if true, a call to is - made immediately following the request - + + An representing the velocity of our agent - - - Select multiple objects. This will cause the to send us - an which will raise the event - - The the objects are located - An array containing the Local IDs of the objects - Should objects be deselected immediately after selection - + + An representing the acceleration of our agent + + + A which specifies the angular speed, and axis about which an Avatar is rotating. + + + Position avatar client will goto when login to 'home' or during + teleport request to 'home' region. + + + LookAt point saved/restored with HomePosition + + + Avatar First Name (i.e. Philip) + + + Avatar Last Name (i.e. Linden) + + + LookAt point received with the login response message + + + Avatar Full Name (i.e. Philip Linden) + + + Gets the health of the agent + + + Gets the current balance of the agent + + + Gets the local ID of the prim the agent is sitting on, + zero if the avatar is not currently sitting + + + Gets the of the agents active group. + + + Gets the Agents powers in the currently active group + + + Current status message for teleporting + + + Current position of the agent as a relative offset from + the simulator, or the parent object if we are sitting on something + + + Current rotation of the agent as a relative rotation from + the simulator, or the parent object if we are sitting on something + + + Current position of the agent in the simulator + + + + A representing the agents current rotation + + + + Returns the global grid position of the avatar + + + + Called once attachment resource usage information has been collected + + Indicates if operation was successfull + Attachment resource usage information + + + + Agent movement and camera control + + Agent movement is controlled by setting specific + After the control flags are set, An AgentUpdate is required to update the simulator of the specified flags + This is most easily accomplished by setting one or more of the AgentMovement properties + + Movement of an avatar is always based on a compass direction, for example AtPos will move the + agent from West to East or forward on the X Axis, AtNeg will of course move agent from + East to West or backward on the X Axis, LeftPos will be South to North or forward on the Y Axis + The Z axis is Up, finer grained control of movements can be done using the Nudge properties + + + + Agent camera controls + + + Currently only used for hiding your group title + + + Action state of the avatar, which can currently be + typing and editing + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Timer for sending AgentUpdate packets + + + Default constructor + + + + Send an AgentUpdate with the camera set at the current agent + position and pointing towards the heading specified + + Camera rotation in radians + Whether to send the AgentUpdate reliable + or not + + + + Rotates the avatar body and camera toward a target position. + This will also anchor the camera position on the avatar + + Region coordinates to turn toward + + + + Rotates the avatar body and camera toward a target position. + This will also anchor the camera position on the avatar + + Region coordinates to turn toward + whether to send update or not + + + + Send new AgentUpdate packet to update our current camera + position and rotation + + + + + Send new AgentUpdate packet to update our current camera + position and rotation + + Whether to require server acknowledgement + of this packet + + + + Send new AgentUpdate packet to update our current camera + position and rotation + + Whether to require server acknowledgement + of this packet + Simulator to send the update to + + + + Builds an AgentUpdate packet entirely from parameters. This + will not touch the state of Self.Movement or + Self.Movement.Camera in any way + + + + + + + + + + + + + + + + Sends update of Field of Vision vertical angle to the simulator + + Angle in radians + + + Move agent positive along the X axis + + + Move agent negative along the X axis + + + Move agent positive along the Y axis + + + Move agent negative along the Y axis + + + Move agent positive along the Z axis + + + Move agent negative along the Z axis + + + + + + + + + + + + + + + + + + + + + + + + Causes simulator to make agent fly + + + Stop movement + + + Finish animation + + + Stand up from a sit + + + Tells simulator to sit agent on ground + + + Place agent into mouselook mode + + + Nudge agent positive along the X axis + + + Nudge agent negative along the X axis + + + Nudge agent positive along the Y axis + + + Nudge agent negative along the Y axis + + + Nudge agent positive along the Z axis + + + Nudge agent negative along the Z axis + + + + + + + + + Tell simulator to mark agent as away + + + + + + + + + + + + + + + + Returns "always run" value, or changes it by sending a SetAlwaysRunPacket + + + + The current value of the agent control flags + + + Gets or sets the interval in milliseconds at which + AgentUpdate packets are sent to the current simulator. Setting + this to a non-zero value will also enable the packet sending if + it was previously off, and setting it to zero will disable + + + Gets or sets whether AgentUpdate packets are sent to + the current simulator + + + Reset movement controls every time we send an update + + + + Camera controls for the agent, mostly a thin wrapper around + CoordinateFrame. This class is only responsible for state + tracking and math, it does not send any packets + + + + + + + The camera is a local frame of reference inside of + the larger grid space. This is where the math happens + + + + Default constructor + + + + + + + + + + + + + + + + + Used to specify movement actions for your agent + + + + Empty flag + + + Move Forward (SL Keybinding: W/Up Arrow) + + + Move Backward (SL Keybinding: S/Down Arrow) + + + Move Left (SL Keybinding: Shift-(A/Left Arrow)) + + + Move Right (SL Keybinding: Shift-(D/Right Arrow)) + + + Not Flying: Jump/Flying: Move Up (SL Keybinding: E) + + + Not Flying: Croutch/Flying: Move Down (SL Keybinding: C) + + + Unused + + + Unused + + + Unused + + + Unused + + + ORed with AGENT_CONTROL_AT_* if the keyboard is being used + + + ORed with AGENT_CONTROL_LEFT_* if the keyboard is being used + + + ORed with AGENT_CONTROL_UP_* if the keyboard is being used + + + Fly + + + + + + Finish our current animation + + + Stand up from the ground or a prim seat + + + Sit on the ground at our current location + + + Whether mouselook is currently enabled + + + Legacy, used if a key was pressed for less than a certain amount of time + + + Legacy, used if a key was pressed for less than a certain amount of time + + + Legacy, used if a key was pressed for less than a certain amount of time + + + Legacy, used if a key was pressed for less than a certain amount of time + + + Legacy, used if a key was pressed for less than a certain amount of time + + + Legacy, used if a key was pressed for less than a certain amount of time + + + + + + + + + Set when the avatar is idled or set to away. Note that the away animation is + activated separately from setting this flag + + + + + + + + + + + + + + + + Class for sending info on the success of the opration + of setting the maturity access level + + + + + Creates new instance of the EventArgs class + + Has setting new maturty access level succeeded + New maturity access level as returned by the simulator + + + + New maturity accesss level returned from the sim + + + + + True if setting the new maturity access level has succedded + + + + + + + + + + Construct a new instance of the ChatEventArgs object + + Sim from which the message originates + The message sent + The audible level of the message + The type of message sent: whisper, shout, etc + The source type of the message sender + The name of the agent or object sending the message + The ID of the agent or object sending the message + The ID of the object owner, or the agent ID sending the message + The position of the agent or object sending the message + + + Get the simulator sending the message + + + Get the message sent + + + Get the audible level of the message + + + Get the type of message sent: whisper, shout, etc + + + Get the source type of the message sender + + + Get the name of the agent or object sending the message + + + Get the ID of the agent or object sending the message + + + Get the ID of the object owner, or the agent ID sending the message + + + Get the position of the agent or object sending the message + + + Contains the data sent when a primitive opens a dialog with this agent + + + + Construct a new instance of the ScriptDialogEventArgs + + The dialog message + The name of the object that sent the dialog request + The ID of the image to be displayed + The ID of the primitive sending the dialog + The first name of the senders owner + The last name of the senders owner + The communication channel the dialog was sent on + The string labels containing the options presented in this dialog + UUID of the scritped object owner + + + Get the dialog message + + + Get the name of the object that sent the dialog request + + + Get the ID of the image to be displayed + + + Get the ID of the primitive sending the dialog + + + Get the first name of the senders owner + + + Get the last name of the senders owner + + + Get the communication channel the dialog was sent on, responses + should also send responses on this same channel + + + Get the string labels containing the options presented in this dialog + + + UUID of the scritped object owner + + + Contains the data sent when a primitive requests debit or other permissions + requesting a YES or NO answer + + + + Construct a new instance of the ScriptQuestionEventArgs + + The simulator containing the object sending the request + The ID of the script making the request + The ID of the primitive containing the script making the request + The name of the primitive making the request + The name of the owner of the object making the request + The permissions being requested + + + Get the simulator containing the object sending the request + + + Get the ID of the script making the request + + + Get the ID of the primitive containing the script making the request + + + Get the name of the primitive making the request + + + Get the name of the owner of the object making the request + + + Get the permissions being requested + + + Contains the data sent when a primitive sends a request + to an agent to open the specified URL + + + + Construct a new instance of the LoadUrlEventArgs + + The name of the object sending the request + The ID of the object sending the request + The ID of the owner of the object sending the request + True if the object is owned by a group + The message sent with the request + The URL the object sent + + + Get the name of the object sending the request + + + Get the ID of the object sending the request + + + Get the ID of the owner of the object sending the request + + + True if the object is owned by a group + + + Get the message sent with the request + + + Get the URL the object sent + + + The date received from an ImprovedInstantMessage + + + + Construct a new instance of the InstantMessageEventArgs object + + the InstantMessage object + the simulator where the InstantMessage origniated + + + Get the InstantMessage object + + + Get the simulator where the InstantMessage origniated + + + Contains the currency balance + + + + Construct a new BalanceEventArgs object + + The currenct balance + + + + Get the currenct balance + + + + Contains the transaction summary when an item is purchased, + money is given, or land is purchased + + + + Construct a new instance of the MoneyBalanceReplyEventArgs object + + The ID of the transaction + True of the transaction was successful + The current currency balance + The meters credited + The meters comitted + A brief description of the transaction + Transaction info + + + Get the ID of the transaction + + + True of the transaction was successful + + + Get the remaining currency balance + + + Get the meters credited + + + Get the meters comitted + + + Get the description of the transaction + + + Detailed transaction information + + + Data sent from the simulator containing information about your agent and active group information + + + + Construct a new instance of the AgentDataReplyEventArgs object + + The agents first name + The agents last name + The agents active group ID + The group title of the agents active group + The combined group powers the agent has in the active group + The name of the group the agent has currently active + + + Get the agents first name + + + Get the agents last name + + + Get the active group ID of your agent + + + Get the active groups title of your agent + + + Get the combined group powers of your agent + + + Get the active group name of your agent + + + Data sent by the simulator to indicate the active/changed animations + applied to your agent + + + + Construct a new instance of the AnimationsChangedEventArgs class + + The dictionary that contains the changed animations + + + Get the dictionary that contains the changed animations + + + + Data sent from a simulator indicating a collision with your agent + + + + + Construct a new instance of the MeanCollisionEventArgs class + + The type of collision that occurred + The ID of the agent or object that perpetrated the agression + The ID of the Victim + The strength of the collision + The Time the collision occurred + + + Get the Type of collision + + + Get the ID of the agent or object that collided with your agent + + + Get the ID of the agent that was attacked + + + A value indicating the strength of the collision + + + Get the time the collision occurred + + + Data sent to your agent when it crosses region boundaries + + + + Construct a new instance of the RegionCrossedEventArgs class + + The simulator your agent just left + The simulator your agent is now in + + + Get the simulator your agent just left + + + Get the simulator your agent is now in + + + Data sent from the simulator when your agent joins a group chat session + + + + Construct a new instance of the GroupChatJoinedEventArgs class + + The ID of the session + The name of the session + A temporary session id used for establishing new sessions + True of your agent successfully joined the session + + + Get the ID of the group chat session + + + Get the name of the session + + + Get the temporary session ID used for establishing new sessions + + + True if your agent successfully joined the session + + + Data sent by the simulator containing urgent messages + + + + Construct a new instance of the AlertMessageEventArgs class + + The alert message + + + Get the alert message + + + Data sent by a script requesting to take or release specified controls to your agent + + + + Construct a new instance of the ScriptControlEventArgs class + + The controls the script is attempting to take or release to the agent + True if the script is passing controls back to the agent + True if the script is requesting controls be released to the script + + + Get the controls the script is attempting to take or release to the agent + + + True if the script is passing controls back to the agent + + + True if the script is requesting controls be released to the script + + + + Data sent from the simulator to an agent to indicate its view limits + + + + + Construct a new instance of the CameraConstraintEventArgs class + + The collision plane + + + Get the collision plane + + + + Data containing script sensor requests which allow an agent to know the specific details + of a primitive sending script sensor requests + + + + + Construct a new instance of the ScriptSensorReplyEventArgs + + The ID of the primitive sending the sensor + The ID of the group associated with the primitive + The name of the primitive sending the sensor + The ID of the primitive sending the sensor + The ID of the owner of the primitive sending the sensor + The position of the primitive sending the sensor + The range the primitive specified to scan + The rotation of the primitive sending the sensor + The type of sensor the primitive sent + The velocity of the primitive sending the sensor + + + Get the ID of the primitive sending the sensor + + + Get the ID of the group associated with the primitive + + + Get the name of the primitive sending the sensor + + + Get the ID of the primitive sending the sensor + + + Get the ID of the owner of the primitive sending the sensor + + + Get the position of the primitive sending the sensor + + + Get the range the primitive specified to scan + + + Get the rotation of the primitive sending the sensor + + + Get the type of sensor the primitive sent + + + Get the velocity of the primitive sending the sensor + + + Contains the response data returned from the simulator in response to a + + + Construct a new instance of the AvatarSitResponseEventArgs object + + + Get the ID of the primitive the agent will be sitting on + + + True if the simulator Autopilot functions were involved + + + Get the camera offset of the agent when seated + + + Get the camera eye offset of the agent when seated + + + True of the agent will be in mouselook mode when seated + + + Get the position of the agent when seated + + + Get the rotation of the agent when seated + + + Data sent when an agent joins a chat session your agent is currently participating in + + + + Construct a new instance of the ChatSessionMemberAddedEventArgs object + + The ID of the chat session + The ID of the agent joining + + + Get the ID of the chat session + + + Get the ID of the agent that joined + + + Data sent when an agent exits a chat session your agent is currently participating in + + + + Construct a new instance of the ChatSessionMemberLeftEventArgs object + + The ID of the chat session + The ID of the Agent that left + + + Get the ID of the chat session + + + Get the ID of the agent that left + + + Event arguments with the result of setting display name operation + + + Default constructor + + + Status code, 200 indicates settign display name was successful + + + Textual description of the status + + + Details of the newly set display name + + + + Throttles the network traffic for various different traffic types. + Access this class through GridClient.Throttle + + + + + Default constructor, uses a default high total of 1500 KBps (1536000) + + + + + Constructor that decodes an existing AgentThrottle packet in to + individual values + + Reference to the throttle data in an AgentThrottle + packet + Offset position to start reading at in the + throttle data + This is generally not needed in clients as the server will + never send a throttle packet to the client + + + + Send an AgentThrottle packet to the current server using the + current values + + + + + Send an AgentThrottle packet to the specified server using the + current values + + + + + Convert the current throttle values to a byte array that can be put + in an AgentThrottle packet + + Byte array containing all the throttle values + + + Maximum bits per second for resending unacknowledged packets + + + Maximum bits per second for LayerData terrain + + + Maximum bits per second for LayerData wind data + + + Maximum bits per second for LayerData clouds + + + Unknown, includes object data + + + Maximum bits per second for textures + + + Maximum bits per second for downloaded assets + + + Maximum bits per second the entire connection, divided up + between invidiual streams using default multipliers + + + + Static pre-defined animations available to all agents + + + + Agent with afraid expression on face + + + Agent aiming a bazooka (right handed) + + + Agent aiming a bow (left handed) + + + Agent aiming a hand gun (right handed) + + + Agent aiming a rifle (right handed) + + + Agent with angry expression on face + + + Agent hunched over (away) + + + Agent doing a backflip + + + Agent laughing while holding belly + + + Agent blowing a kiss + + + Agent with bored expression on face + + + Agent bowing to audience + + + Agent brushing himself/herself off + + + Agent in busy mode + + + Agent clapping hands + + + Agent doing a curtsey bow + + + Agent crouching + + + Agent crouching while walking + + + Agent crying + + + Agent unanimated with arms out (e.g. setting appearance) + + + Agent re-animated after set appearance finished + + + Agent dancing + + + Agent dancing + + + Agent dancing + + + Agent dancing + + + Agent dancing + + + Agent dancing + + + Agent dancing + + + Agent dancing + + + Agent on ground unanimated + + + Agent boozing it up + + + Agent with embarassed expression on face + + + Agent with afraid expression on face + + + Agent with angry expression on face + + + Agent with bored expression on face + + + Agent crying + + + Agent showing disdain (dislike) for something + + + Agent with embarassed expression on face + + + Agent with frowning expression on face + + + Agent with kissy face + + + Agent expressing laughgter + + + Agent with open mouth + + + Agent with repulsed expression on face + + + Agent expressing sadness + + + Agent shrugging shoulders + + + Agent with a smile + + + Agent expressing surprise + + + Agent sticking tongue out + + + Agent with big toothy smile + + + Agent winking + + + Agent expressing worry + + + Agent falling down + + + Agent walking (feminine version) + + + Agent wagging finger (disapproval) + + + I'm not sure I want to know + + + Agent in superman position + + + Agent in superman position + + + Agent greeting another + + + Agent holding bazooka (right handed) + + + Agent holding a bow (left handed) + + + Agent holding a handgun (right handed) + + + Agent holding a rifle (right handed) + + + Agent throwing an object (right handed) + + + Agent in static hover + + + Agent hovering downward + + + Agent hovering upward + + + Agent being impatient + + + Agent jumping + + + Agent jumping with fervor + + + Agent point to lips then rear end + + + Agent landing from jump, finished flight, etc + + + Agent laughing + + + Agent landing from jump, finished flight, etc + + + Agent sitting on a motorcycle + + + + + + Agent moving head side to side + + + Agent moving head side to side with unhappy expression + + + Agent taunting another + + + + + + Agent giving peace sign + + + Agent pointing at self + + + Agent pointing at another + + + Agent preparing for jump (bending knees) + + + Agent punching with left hand + + + Agent punching with right hand + + + Agent acting repulsed + + + Agent trying to be Chuck Norris + + + Rocks, Paper, Scissors 1, 2, 3 + + + Agent with hand flat over other hand + + + Agent with fist over other hand + + + Agent with two fingers spread over other hand + + + Agent running + + + Agent appearing sad + + + Agent saluting + + + Agent shooting bow (left handed) + + + Agent cupping mouth as if shouting + + + Agent shrugging shoulders + + + Agent in sit position + + + Agent in sit position (feminine) + + + Agent in sit position (generic) + + + Agent sitting on ground + + + Agent sitting on ground + + + + + + Agent sleeping on side + + + Agent smoking + + + Agent inhaling smoke + + + + + + Agent taking a picture + + + Agent standing + + + Agent standing up + + + Agent standing + + + Agent standing + + + Agent standing + + + Agent standing + + + Agent stretching + + + Agent in stride (fast walk) + + + Agent surfing + + + Agent acting surprised + + + Agent striking with a sword + + + Agent talking (lips moving) + + + Agent throwing a tantrum + + + Agent throwing an object (right handed) + + + Agent trying on a shirt + + + Agent turning to the left + + + Agent turning to the right + + + Agent typing + + + Agent walking + + + Agent whispering + + + Agent whispering with fingers in mouth + + + Agent winking + + + Agent winking + + + Agent worried + + + Agent nodding yes + + + Agent nodding yes with happy face + + + Agent floating with legs and arms crossed + + + + A dictionary containing all pre-defined animations + + A dictionary containing the pre-defined animations, + where the key is the animations ID, and the value is a string + containing a name to identify the purpose of the animation + + + + Index of TextureEntry slots for avatar appearances + + + + + Bake layers for avatar appearance + + + + + Appearance Flags, introdued with server side baking, currently unused + + + + Maximum number of concurrent downloads for wearable assets and textures + + + Maximum number of concurrent uploads for baked textures + + + Timeout for fetching inventory listings + + + Timeout for fetching a single wearable, or receiving a single packet response + + + Timeout for fetching a single texture + + + Timeout for uploading a single baked texture + + + Number of times to retry bake upload + + + When changing outfit, kick off rebake after + 20 seconds has passed since the last change + + + Total number of wearables for each avatar + + + Total number of baked textures on each avatar + + + Total number of wearables per bake layer + + + Mask for multiple attachments + + + Mapping between BakeType and AvatarTextureIndex + + + Map of what wearables are included in each bake + + + Magic values to finalize the cache check hashes for each + bake + + + Default avatar texture, used to detect when a custom + texture is not set for a face + + + The event subscribers. null if no subcribers + + + Raises the AgentWearablesReply event + An AgentWearablesReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the CachedBakesReply event + An AgentCachedBakesReplyEventArgs object containing the + data returned from the data server AgentCachedTextureResponse + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the AppearanceSet event + An AppearanceSetEventArgs object indicating if the operatin was successfull + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the RebakeAvatarRequested event + An RebakeAvatarTexturesEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + Visual parameters last sent to the sim + + + Textures about this client sent to the sim + + + A cache of wearables currently being worn + + + A cache of textures currently being worn + + + Incrementing serial number for AgentCachedTexture packets + + + Incrementing serial number for AgentSetAppearance packets + + + Indicates if WearablesRequest succeeded + + + Indicates whether or not the appearance thread is currently + running, to prevent multiple appearance threads from running + simultaneously + + + Reference to our agent + + + + Timer used for delaying rebake on changing outfit + + + + + Main appearance thread + + + + + Is server baking complete. It needs doing only once + + + + + Default constructor + + A reference to our agent + + + + Obsolete method for setting appearance. This function no longer does anything. + Use RequestSetAppearance() to manually start the appearance thread + + + + + Obsolete method for setting appearance. This function no longer does anything. + Use RequestSetAppearance() to manually start the appearance thread + + Unused parameter + + + + Starts the appearance setting thread + + + + + Starts the appearance setting thread + + True to force rebaking, otherwise false + + + + Check if current region supports server side baking + + True if server side baking support is detected + + + + Ask the server what textures our agent is currently wearing + + + + + Build hashes out of the texture assetIDs for each baking layer to + ask the simulator whether it has cached copies of each baked texture + + + + + Returns the AssetID of the asset that is currently being worn in a + given WearableType slot + + WearableType slot to get the AssetID for + The UUID of the asset being worn in the given slot, or + UUID.Zero if no wearable is attached to the given slot or wearables + have not been downloaded yet + + + + Add a wearable to the current outfit and set appearance + + Wearable to be added to the outfit + + + + Add a wearable to the current outfit and set appearance + + Wearable to be added to the outfit + Should existing item on the same point or of the same type be replaced + + + + Add a list of wearables to the current outfit and set appearance + + List of wearable inventory items to + be added to the outfit + Should existing item on the same point or of the same type be replaced + + + + Add a list of wearables to the current outfit and set appearance + + List of wearable inventory items to + be added to the outfit + Should existing item on the same point or of the same type be replaced + + + + Remove a wearable from the current outfit and set appearance + + Wearable to be removed from the outfit + + + + Removes a list of wearables from the current outfit and set appearance + + List of wearable inventory items to + be removed from the outfit + + + + Replace the current outfit with a list of wearables and set appearance + + List of wearable inventory items that + define a new outfit + + + + Replace the current outfit with a list of wearables and set appearance + + List of wearable inventory items that + define a new outfit + Check if we have all body parts, set this to false only + if you know what you're doing + + + + Checks if an inventory item is currently being worn + + The inventory item to check against the agent + wearables + The WearableType slot that the item is being worn in, + or WearbleType.Invalid if it is not currently being worn + + + + Returns a copy of the agents currently worn wearables + + A copy of the agents currently worn wearables + Avoid calling this function multiple times as it will make + a copy of all of the wearable data each time + + + + Calls either or + depending on the value of + replaceItems + + List of wearable inventory items to add + to the outfit or become a new outfit + True to replace existing items with the + new list of items, false to add these items to the existing outfit + + + + Adds a list of attachments to our agent + + A List containing the attachments to add + If true, tells simulator to remove existing attachment + first + + + + Adds a list of attachments to our agent + + A List containing the attachments to add + If true, tells simulator to remove existing attachment + If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments) + first + + + + Attach an item to our agent at a specific attach point + + A to attach + the on the avatar + to attach the item to + + + + Attach an item to our agent at a specific attach point + + A to attach + the on the avatar + If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments) + to attach the item to + + + + Attach an item to our agent specifying attachment details + + The of the item to attach + The attachments owner + The name of the attachment + The description of the attahment + The to apply when attached + The of the attachment + The on the agent + to attach the item to + + + + Attach an item to our agent specifying attachment details + + The of the item to attach + The attachments owner + The name of the attachment + The description of the attahment + The to apply when attached + The of the attachment + The on the agent + If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments) + to attach the item to + + + + Detach an item from our agent using an object + + An object + + + + Detach an item from our agent + + The inventory itemID of the item to detach + + + + Inform the sim which wearables are part of our current outfit + + + + + Replaces the Wearables collection with a list of new wearable items + + Wearable items to replace the Wearables collection with + + + + Calculates base color/tint for a specific wearable + based on its params + + All the color info gathered from wearable's VisualParams + passed as list of ColorParamInfo tuples + Base color/tint for the wearable + + + + Blocking method to populate the Wearables dictionary + + True on success, otherwise false + + + + Blocking method to populate the Textures array with cached bakes + + True on success, otherwise false + + + + Populates textures and visual params from a decoded asset + + Wearable to decode + + Populates textures and visual params from a decoded asset + + Wearable to decode + + + + Blocking method to download and parse currently worn wearable assets + + True on success, otherwise false + + + + Get a list of all of the textures that need to be downloaded for a + single bake layer + + Bake layer to get texture AssetIDs for + A list of texture AssetIDs to download + + + + Helper method to lookup the TextureID for a single layer and add it + to a list if it is not already present + + + + + + + Blocking method to download all of the textures needed for baking + the given bake layers + + A list of layers that need baking + No return value is given because the baking will happen + whether or not all textures are successfully downloaded + + + + Blocking method to create and upload baked textures for all of the + missing bakes + + True on success, otherwise false + + + + Blocking method to create and upload a baked texture for a single + bake layer + + Layer to bake + True on success, otherwise false + + + + Blocking method to upload a baked texture + + Five channel JPEG2000 texture data to upload + UUID of the newly created asset on success, otherwise UUID.Zero + + + + Creates a dictionary of visual param values from the downloaded wearables + + A dictionary of visual param indices mapping to visual param + values for our agent that can be fed to the Baker class + + + + Initate server baking process + + True if the server baking was successful + + + + Get the latest version of COF + + Current Outfit Folder (or null if getting the data failed) + + + + Create an AgentSetAppearance packet from Wearables data and the + Textures array and send it + + + + + Converts a WearableType to a bodypart or clothing WearableType + + A WearableType + AssetType.Bodypart or AssetType.Clothing or AssetType.Unknown + + + + Converts a BakeType to the corresponding baked texture slot in AvatarTextureIndex + + A BakeType + The AvatarTextureIndex slot that holds the given BakeType + + + + Gives the layer number that is used for morph mask + + >A BakeType + Which layer number as defined in BakeTypeToTextures is used for morph mask + + + + Converts a BakeType to a list of the texture slots that make up that bake + + A BakeType + A list of texture slots that are inputs for the given bake + + + Triggered when an AgentWearablesUpdate packet is received, + telling us what our avatar is currently wearing + request. + + + Raised when an AgentCachedTextureResponse packet is + received, giving a list of cached bakes that were found on the + simulator + request. + + + + Raised when appearance data is sent to the simulator, also indicates + the main appearance thread is finished. + + request. + + + + Triggered when the simulator requests the agent rebake its appearance. + + + + + + Returns true if AppearanceManager is busy and trying to set or change appearance will fail + + + + + Contains information about a wearable inventory item + + + + Inventory ItemID of the wearable + + + AssetID of the wearable asset + + + WearableType of the wearable + + + AssetType of the wearable + + + Asset data for the wearable + + + + Data collected from visual params for each wearable + needed for the calculation of the color + + + + + Holds a texture assetID and the data needed to bake this layer into + an outfit texture. Used to keep track of currently worn textures + and baking data + + + + A texture AssetID + + + Asset data for the texture + + + Collection of alpha masks that needs applying + + + Tint that should be applied to the texture + + + Where on avatar does this texture belong + + + Contains the Event data returned from the data server from an AgentWearablesRequest + + + Construct a new instance of the AgentWearablesReplyEventArgs class + + + Contains the Event data returned from the data server from an AgentCachedTextureResponse + + + Construct a new instance of the AgentCachedBakesReplyEventArgs class + + + Contains the Event data returned from an AppearanceSetRequest + + + + Triggered when appearance data is sent to the sim and + the main appearance thread is done. + Indicates whether appearance setting was successful + + + Indicates whether appearance setting was successful + + + Contains the Event data returned from the data server from an RebakeAvatarTextures + + + + Triggered when the simulator sends a request for this agent to rebake + its appearance + + The ID of the Texture Layer to bake + + + The ID of the Texture Layer to bake + + + + Class that handles the local asset cache + + + + + Default constructor + + A reference to the GridClient object + + + + Disposes cleanup timer + + + + + Only create timer when needed + + + + + Return bytes read from the local asset cache, null if it does not exist + + UUID of the asset we want to get + Raw bytes of the asset, or null on failure + + + + Returns ImageDownload object of the + image from the local image cache, null if it does not exist + + UUID of the image we want to get + ImageDownload object containing the image, or null on failure + + + + Constructs a file name of the cached asset + + UUID of the asset + String with the file name of the cahced asset + + + + Constructs a file name of the static cached asset + + UUID of the asset + String with the file name of the static cached asset + + + + Saves an asset to the local cache + + UUID of the asset + Raw bytes the asset consists of + Weather the operation was successfull + + + + Get the file name of the asset stored with gived UUID + + UUID of the asset + Null if we don't have that UUID cached on disk, file name if found in the cache folder + + + + Checks if the asset exists in the local cache + + UUID of the asset + True is the asset is stored in the cache, otherwise false + + + + Wipes out entire cache + + + + + Brings cache size to the 90% of the max size + + + + + Asynchronously brings cache size to the 90% of the max size + + + + + Adds up file sizes passes in a FileInfo array + + + + + Checks whether caching is enabled + + + + + Periodically prune the cache + + + + + Nicely formats file sizes + + Byte size we want to output + String with humanly readable file size + + + + Allows setting weather to periodicale prune the cache if it grows too big + Default is enabled, when caching is enabled + + + + + How long (in ms) between cache checks (default is 5 min.) + + + + + Helper class for sorting files by their last accessed time + + + + + + + + + OK + + + Transfer completed + + + + + + + + + Unknown error occurred + + + Equivalent to a 404 error + + + Client does not have permission for that resource + + + Unknown status + + + + + + + + + + + Unknown + + + Virtually all asset transfers use this channel + + + + + + + + + + + Asset from the asset server + + + Inventory item + + + Estate asset, such as an estate covenant + + + + + + + + + + + + + + + + + + When requesting image download, type of the image requested + + + + Normal in-world object texture + + + Avatar texture + + + Server baked avatar texture + + + + Image file format + + + + + + + + + Number of milliseconds passed since the last transfer + packet was received + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Number of milliseconds to wait for a transfer header packet if out of order data was received + + + The event subscribers. null if no subcribers + + + Raises the XferReceived event + A XferReceivedEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the AssetUploaded event + A AssetUploadedEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the UploadProgress event + A UploadProgressEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the InitiateDownload event + A InitiateDownloadEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the ImageReceiveProgress event + A ImageReceiveProgressEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + Texture download cache + + + + Default constructor + + A reference to the GridClient object + + + + Request an asset download + + Asset UUID + Asset type, must be correct for the transfer to succeed + Whether to give this transfer an elevated priority + The callback to fire when the simulator responds with the asset data + + + + Request an asset download + + Asset UUID + Asset type, must be correct for the transfer to succeed + Whether to give this transfer an elevated priority + Source location of the requested asset + The callback to fire when the simulator responds with the asset data + + + + Request an asset download + + Asset UUID + Asset type, must be correct for the transfer to succeed + Whether to give this transfer an elevated priority + Source location of the requested asset + UUID of the transaction + The callback to fire when the simulator responds with the asset data + + + + Request an asset download + + Asset UUID + Asset type, must be correct for the transfer to succeed + Whether to give this transfer an elevated priority + Source location of the requested asset + UUID of the transaction + The callback to fire when the simulator responds with the asset data + + + + Request an asset download through the almost deprecated Xfer system + + Filename of the asset to request + Whether or not to delete the asset + off the server after it is retrieved + Use large transfer packets or not + UUID of the file to request, if filename is + left empty + Asset type of vFileID, or + AssetType.Unknown if filename is not empty + Sets the FilePath in the request to Cache + (4) if true, otherwise Unknown (0) is used + + + + + + + Use UUID.Zero if you do not have the + asset ID but have all the necessary permissions + The item ID of this asset in the inventory + Use UUID.Zero if you are not requesting an + asset from an object inventory + The owner of this asset + Asset type + Whether to prioritize this asset download or not + + + + + Used to force asset data into the PendingUpload property, ie: for raw terrain uploads + + An AssetUpload object containing the data to upload to the simulator + + + + Request an asset be uploaded to the simulator + + The Object containing the asset data + If True, the asset once uploaded will be stored on the simulator + in which the client was connected in addition to being stored on the asset server + The of the transfer, can be used to correlate the upload with + events being fired + + + + Request an asset be uploaded to the simulator + + The of the asset being uploaded + A byte array containing the encoded asset data + If True, the asset once uploaded will be stored on the simulator + in which the client was connected in addition to being stored on the asset server + The of the transfer, can be used to correlate the upload with + events being fired + + + + Request an asset be uploaded to the simulator + + + Asset type to upload this data as + A byte array containing the encoded asset data + If True, the asset once uploaded will be stored on the simulator + in which the client was connected in addition to being stored on the asset server + The of the transfer, can be used to correlate the upload with + events being fired + + + + Initiate an asset upload + + The ID this asset will have if the + upload succeeds + Asset type to upload this data as + Raw asset data to upload + Whether to store this asset on the local + simulator or the grid-wide asset server + The tranaction id for the upload + The transaction ID of this transfer + + + + Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + A float indicating the requested priority for the transfer. Higher priority values tell the simulator + to prioritize the request before lower valued requests. An image already being transferred using the can have + its priority changed by resending the request with the new priority value + Number of quality layers to discard. + This controls the end marker of the data sent. Sending with value -1 combined with priority of 0 cancels an in-progress + transfer. + A bug exists in the Linden Simulator where a -1 will occasionally be sent with a non-zero priority + indicating an off-by-one error. + The packet number to begin the request at. A value of 0 begins the request + from the start of the asset texture + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + If true, the callback will be fired for each chunk of the downloaded image. + The callback asset parameter will contain all previously received chunks of the texture asset starting + from the beginning of the request + + Request an image and fire a callback when the request is complete + + Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); + + private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) + { + if(state == TextureRequestState.Finished) + { + Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", + asset.AssetID, + asset.AssetData.Length); + } + } + + Request an image and use an inline anonymous method to handle the downloaded texture data + + Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, delegate(TextureRequestState state, AssetTexture asset) + { + if(state == TextureRequestState.Finished) + { + Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", + asset.AssetID, + asset.AssetData.Length); + } + } + ); + + Request a texture, decode the texture to a bitmap image and apply it to a imagebox + + Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); + + private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) + { + if(state == TextureRequestState.Finished) + { + ManagedImage imgData; + Image bitmap; + + if (state == TextureRequestState.Finished) + { + OpenJPEG.DecodeToImage(assetTexture.AssetData, out imgData, out bitmap); + picInsignia.Image = bitmap; + } + } + } + + + + + + Overload: Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + + The of the texture asset to download + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + + + + Overload: Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + + + + Overload: Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + If true, the callback will be fired for each chunk of the downloaded image. + The callback asset parameter will contain all previously received chunks of the texture asset starting + from the beginning of the request + + + + Cancel a texture request + + The texture assets + + + + Requests download of a mesh asset + + UUID of the mesh asset + Callback when the request completes + + + + Fetach avatar texture on a grid capable of server side baking + + ID of the avatar + ID of the texture + Name of the part of the avatar texture applies to + Callback invoked on operation completion + + + + Lets TexturePipeline class fire the progress event + + The texture ID currently being downloaded + the number of bytes transferred + the total number of bytes expected + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Raised when the simulator responds sends + + + Raised during upload completes + + + Raised during upload with progres update + + + Fired when the simulator sends an InitiateDownloadPacket, used to download terrain .raw files + + + Fired when a texture is in the process of being downloaded by the TexturePipeline class + + + + Callback used for various asset download requests + + Transfer information + Downloaded asset, null on fail + + + + Callback used upon competition of baked texture upload + + Asset UUID of the newly uploaded baked texture + + + + A callback that fires upon the completition of the RequestMesh call + + Was the download successfull + Resulting mesh or null on problems + + + Xfer data + + + Upload data + + + Filename used on the simulator + + + Filename used by the client + + + UUID of the image that is in progress + + + Number of bytes received so far + + + Image size in bytes + + + + Avatar profile flags + + + + + Represents an avatar (other than your own) + + + + + Particle system specific enumerators, flags and methods. + + + + + Current version of the media data for the prim + + + + + Array of media entries indexed by face number + + + + + + + + + + + + + + + + + + + + + + + + + Foliage type for this primitive. Only applicable if this + primitive is foliage + + + Unknown + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Identifies the owner if audio or a particle system is + active + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Objects physics engine propertis + + + Extra data about primitive + + + Indicates if prim is attached to an avatar + + + Number of clients referencing this prim + + + + Default constructor + + + + + Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew + parameters in to signed eight bit values + + Floating point parameter to pack + Signed eight bit value containing the packed parameter + + + + Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew + parameters from signed eight bit integers to floating point values + + Signed eight bit value to unpack + Unpacked floating point value + + + + + + + + + Uses basic heuristics to estimate the primitive shape + + + + Complete structure for the particle system + + + + Particle Flags + There appears to be more data packed in to this area + for many particle systems. It doesn't appear to be flag values + and serialization breaks unless there is a flag for every + possible bit so it is left as an unsigned integer + + + pattern of particles + + + A representing the maximimum age (in seconds) particle will be displayed + Maximum value is 30 seconds + + + A representing the number of seconds, + from when the particle source comes into view, + or the particle system's creation, that the object will emits particles; + after this time period no more particles are emitted + + + A in radians that specifies where particles will not be created + + + A in radians that specifies where particles will be created + + + A representing the number of seconds between burts. + + + A representing the number of meters + around the center of the source where particles will be created. + + + A representing in seconds, the minimum speed between bursts of new particles + being emitted + + + A representing in seconds the maximum speed of new particles being emitted. + + + A representing the maximum number of particles emitted per burst + + + A which represents the velocity (speed) from the source which particles are emitted + + + A which represents the Acceleration from the source which particles are emitted + + + The Key of the texture displayed on the particle + + + The Key of the specified target object or avatar particles will follow + + + Flags of particle from + + + Max Age particle system will emit particles for + + + The the particle has at the beginning of its lifecycle + + + The the particle has at the ending of its lifecycle + + + A that represents the starting X size of the particle + Minimum value is 0, maximum value is 4 + + + A that represents the starting Y size of the particle + Minimum value is 0, maximum value is 4 + + + A that represents the ending X size of the particle + Minimum value is 0, maximum value is 4 + + + A that represents the ending Y size of the particle + Minimum value is 0, maximum value is 4 + + + A that represents the start glow value + Minimum value is 0, maximum value is 1 + + + A that represents the end glow value + Minimum value is 0, maximum value is 1 + + + OpenGL blend function to use at particle source + + + OpenGL blend function to use at particle destination + + + + Can this particle system be packed in a legacy compatible way + + True if the particle system doesn't use new particle system features + + + + Decodes a byte[] array into a ParticleSystem Object + + ParticleSystem object + Start position for BitPacker + + + + Generate byte[] array from particle data + + Byte array + + + + Particle source pattern + + + + None + + + Drop particles from source position with no force + + + "Explode" particles in all directions + + + Particles shoot across a 2D area + + + Particles shoot across a 3D Cone + + + Inverse of AngleCone (shoot particles everywhere except the 3D cone defined + + + + Particle Data Flags + + + + None + + + Interpolate color and alpha from start to end + + + Interpolate scale from start to end + + + Bounce particles off particle sources Z height + + + velocity of particles is dampened toward the simulators wind + + + Particles follow the source + + + Particles point towards the direction of source's velocity + + + Target of the particles + + + Particles are sent in a straight line + + + Particles emit a glow + + + used for point/grab/touch + + + continuous ribbon particle + + + particle data contains glow + + + particle data contains blend functions + + + + Particle Flags Enum + + + + None + + + Acceleration and velocity for particles are + relative to the object rotation + + + Particles use new 'correct' angle parameters + + + + Parameters used to construct a visual representation of a primitive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Calculdates hash code for prim construction data + + The has + + + Attachment point to an avatar + + + + + + + + + + + + + + + + Information on the flexible properties of a primitive + + + + + + + + + + + + + + + + + + + + + + + Default constructor + + + + + + + + + + + + + + + + + + + + + + + + Information on the light properties of a primitive + + + + + + + + + + + + + + + + + + + + Default constructor + + + + + + + + + + + + + + + + + + + + + + + + Information on the light properties of a primitive as texture map + + + + + + + + + + + Default constructor + + + + + + + + + + + + + + + + + + + + + + + + Information on the sculpt properties of a sculpted primitive + + + + + Default constructor + + + + + + + + + + + + Render inside out (inverts the normals). + + + + + Render an X axis mirror of the sculpty. + + + + + Extended properties to describe an object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default constructor + + + + + Set the properties that are set in an ObjectPropertiesFamily packet + + that has + been partially filled by an ObjectPropertiesFamily packet + + + + Describes physics attributes of the prim + + + + Primitive's local ID + + + Density (1000 for normal density) + + + Friction + + + Gravity multiplier (1 for normal gravity) + + + Type of physics representation of this primitive in the simulator + + + Restitution + + + + Creates PhysicsProperties from OSD + + OSDMap with incoming data + Deserialized PhysicsProperties object + + + + Serializes PhysicsProperties to OSD + + OSDMap with serialized PhysicsProperties data + + + + Texture animation mode + + + + Disable texture animation + + + Enable texture animation + + + Loop when animating textures + + + Animate in reverse direction + + + Animate forward then reverse + + + Slide texture smoothly instead of frame-stepping + + + Rotate texture instead of using frames + + + Scale texture instead of using frames + + + + A single textured face. Don't instantiate this class yourself, use the + methods in TextureEntry + + + + + Contains the definition for individual faces + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + In the future this will specify whether a webpage is + attached to this face + + + + + + + + + + Represents all of the texturable faces for an object + + Grid objects have infinite faces, with each face + using the properties of the default face unless set otherwise. So if + you have a TextureEntry with a default texture uuid of X, and face 18 + has a texture UUID of Y, every face would be textured with X except for + face 18 that uses Y. In practice however, primitives utilize a maximum + of nine faces + + + + + + + + + + Constructor that takes a default texture UUID + + Texture UUID to use as the default texture + + + + Constructor that takes a TextureEntryFace for the + default face + + Face to use as the default face + + + + Constructor that creates the TextureEntry class from a byte array + + Byte array containing the TextureEntry field + Starting position of the TextureEntry field in + the byte array + Length of the TextureEntry field, in bytes + + + + This will either create a new face if a custom face for the given + index is not defined, or return the custom face for that index if + it already exists + + The index number of the face to create or + retrieve + A TextureEntryFace containing all the properties for that + face + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Controls the texture animation of a particular prim + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Groups that this avatar is a member of + + + Positive and negative ratings + + + Avatar properties including about text, profile URL, image IDs and + publishing settings + + + Avatar interests including spoken languages, skills, and "want to" + choices + + + Movement control flags for avatars. Typically not set or used by + clients. To move your avatar, use Client.Self.Movement instead + + + + Contains the visual parameters describing the deformation of the avatar + + + + + Appearance version. Value greater than 0 indicates using server side baking + + + + + Version of the Current Outfit Folder that the appearance is based on + + + + + Appearance flags. Introduced with server side baking, currently unused. + + + + + List of current avatar animations + + + + + Default constructor + + + + First name + + + Last name + + + Full name + + + Active group + + + + Positive and negative ratings + + + + Positive ratings for Behavior + + + Negative ratings for Behavior + + + Positive ratings for Appearance + + + Negative ratings for Appearance + + + Positive ratings for Building + + + Negative ratings for Building + + + Positive ratings given by this avatar + + + Negative ratings given by this avatar + + + + Avatar properties including about text, profile URL, image IDs and + publishing settings + + + + First Life about text + + + First Life image ID + + + + + + + + + + + + + + + Profile image ID + + + Flags of the profile + + + Web URL for this profile + + + Should this profile be published on the web + + + Avatar Online Status + + + Is this a mature profile + + + + + + + + + + Avatar interests including spoken languages, skills, and "want to" + choices + + + + Languages profile field + + + + + + + + + + + + + + + Information about agents display name + + + Agent UUID + + + Username + + + Display name + + + First name (legacy) + + + Last name (legacy) + + + Is display name default display name + + + Cache display name until + + + Last updated timestamp + + + + Creates AgentDisplayName object from OSD + + Incoming OSD data + AgentDisplayName object + + + + Return object as OSD map + + OSD containing agent's display name data + + + Full name (legacy) + + + + Holds group information for Avatars such as those you might find in a profile + + + + true of Avatar accepts group notices + + + Groups Key + + + Texture Key for groups insignia + + + Name of the group + + + Powers avatar has in the group + + + Avatars Currently selected title + + + true of Avatar has chosen to list this in their profile + + + + Contains an animation currently being played by an agent + + + + The ID of the animation asset + + + A number to indicate start order of currently playing animations + On Linden Grids this number is unique per region, with OpenSim it is per client + + + + + + + Holds group information on an individual profile pick + + + + + Retrieve friend status notifications, and retrieve avatar names and + profiles + + + + The event subscribers, null of no subscribers + + + Raises the AvatarAnimation Event + An AvatarAnimationEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the AvatarAppearance Event + A AvatarAppearanceEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the UUIDNameReply Event + A UUIDNameReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the AvatarInterestsReply Event + A AvatarInterestsReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the AvatarPropertiesReply Event + A AvatarPropertiesReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the AvatarGroupsReply Event + A AvatarGroupsReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the AvatarPickerReply Event + A AvatarPickerReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the ViewerEffectPointAt Event + A ViewerEffectPointAtEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the ViewerEffectLookAt Event + A ViewerEffectLookAtEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the ViewerEffect Event + A ViewerEffectEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the AvatarPicksReply Event + A AvatarPicksReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the PickInfoReply Event + A PickInfoReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the AvatarClassifiedReply Event + A AvatarClassifiedReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the ClassifiedInfoReply Event + A ClassifiedInfoReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the DisplayNameUpdate Event + A DisplayNameUpdateEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + + Represents other avatars + + + + + Tracks the specified avatar on your map + Avatar ID to track + + + + Request a single avatar name + + The avatar key to retrieve a name for + + + + Request a list of avatar names + + The avatar keys to retrieve names for + + + + Check if Display Names functionality is available + + True if Display name functionality is available + + + + Request retrieval of display names (max 90 names per request) + + List of UUIDs to lookup + Callback to report result of the operation + + + + Start a request for Avatar Properties + + + + + + Search for an avatar (first name, last name) + + The name to search for + An ID to associate with this query + + + + Start a request for Avatar Picks + + UUID of the avatar + + + + Start a request for Avatar Classifieds + + UUID of the avatar + + + + Start a request for details of a specific profile pick + + UUID of the avatar + UUID of the profile pick + + + + Start a request for details of a specific profile classified + + UUID of the avatar + UUID of the profile classified + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + + EQ Message fired when someone nearby changes their display name + + The message key + the IMessage object containing the deserialized data sent from the simulator + The which originated the packet + + + + Crossed region handler for message that comes across the EventQueue. Sent to an agent + when the agent crosses a sim border into a new region. + + The message key + the IMessage object containing the deserialized data sent from the simulator + The which originated the packet + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Raised when the simulator sends us data containing + an agents animation playlist + + + Raised when the simulator sends us data containing + the appearance information for an agent + + + Raised when the simulator sends us data containing + agent names/id values + + + Raised when the simulator sends us data containing + the interests listed in an agents profile + + + Raised when the simulator sends us data containing + profile property information for an agent + + + Raised when the simulator sends us data containing + the group membership an agent is a member of + + + Raised when the simulator sends us data containing + name/id pair + + + Raised when the simulator sends us data containing + the objects and effect when an agent is pointing at + + + Raised when the simulator sends us data containing + the objects and effect when an agent is looking at + + + Raised when the simulator sends us data containing + an agents viewer effect information + + + Raised when the simulator sends us data containing + the top picks from an agents profile + + + Raised when the simulator sends us data containing + the Pick details + + + Raised when the simulator sends us data containing + the classified ads an agent has placed + + + Raised when the simulator sends us data containing + the details of a classified ad + + + Raised when the simulator sends us data containing + the details of display name change + + + + Callback giving results when fetching display names + + If the request was successful + Array of display names + Array of UUIDs that could not be fetched + + + Provides data for the event + The event occurs when the simulator sends + the animation playlist for an agent + + The following code example uses the and + properties to display the animation playlist of an avatar on the window. + + // subscribe to the event + Client.Avatars.AvatarAnimation += Avatars_AvatarAnimation; + + private void Avatars_AvatarAnimation(object sender, AvatarAnimationEventArgs e) + { + // create a dictionary of "known" animations from the Animations class using System.Reflection + Dictionary<UUID, string> systemAnimations = new Dictionary<UUID, string>(); + Type type = typeof(Animations); + System.Reflection.FieldInfo[] fields = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + foreach (System.Reflection.FieldInfo field in fields) + { + systemAnimations.Add((UUID)field.GetValue(type), field.Name); + } + + // find out which animations being played are known animations and which are assets + foreach (Animation animation in e.Animations) + { + if (systemAnimations.ContainsKey(animation.AnimationID)) + { + Console.WriteLine("{0} is playing {1} ({2}) sequence {3}", e.AvatarID, + systemAnimations[animation.AnimationID], animation.AnimationSequence); + } + else + { + Console.WriteLine("{0} is playing {1} (Asset) sequence {2}", e.AvatarID, + animation.AnimationID, animation.AnimationSequence); + } + } + } + + + + + + Construct a new instance of the AvatarAnimationEventArgs class + + The ID of the agent + The list of animations to start + + + Get the ID of the agent + + + Get the list of animations to start + + + Provides data for the event + The event occurs when the simulator sends + the appearance data for an avatar + + The following code example uses the and + properties to display the selected shape of an avatar on the window. + + // subscribe to the event + Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; + + // handle the data when the event is raised + void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) + { + Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") + } + + + + + + Construct a new instance of the AvatarAppearanceEventArgs class + + The simulator request was from + The ID of the agent + true of the agent is a trial account + The default agent texture + The agents appearance layer textures + The for the agent + + + Get the Simulator this request is from of the agent + + + Get the ID of the agent + + + true if the agent is a trial account + + + Get the default agent texture + + + Get the agents appearance layer textures + + + Get the for the agent + + + Version of the appearance system used. + Value greater than 0 indicates that server side baking is used + + + Version of the Current Outfit Folder the appearance is based on + + + Appearance flags, introduced with server side baking, currently unused + + + Represents the interests from the profile of an agent + + + Get the ID of the agent + + + The properties of an agent + + + Get the ID of the agent + + + Get the ID of the agent + + + Get the ID of the agent + + + Get the ID of the avatar + + + + Event args class for display name notification messages + + + + + Wrapper around a byte array that allows bit to be packed and unpacked + one at a time or by a variable amount. Useful for very tightly packed + data like LayerData packets + + + + + + + + Default constructor, initialize the bit packer / bit unpacker + with a byte array and starting position + + Byte array to pack bits in to or unpack from + Starting position in the byte array + + + + Pack a floating point value in to the data + + Floating point value to pack + + + + Pack part or all of an integer in to the data + + Integer containing the data to pack + Number of bits of the integer to pack + + + + Pack part or all of an unsigned integer in to the data + + Unsigned integer containing the data to pack + Number of bits of the integer to pack + + + + Pack a single bit in to the data + + Bit to pack + + + + + + + + + + + + + + + + + + + + + + + + + Unpacking a floating point value from the data + + Unpacked floating point value + + + + Unpack a variable number of bits from the data in to integer format + + Number of bits to unpack + An integer containing the unpacked bits + This function is only useful up to 32 bits + + + + Unpack a variable number of bits from the data in to unsigned + integer format + + Number of bits to unpack + An unsigned integer containing the unpacked bits + This function is only useful up to 32 bits + + + + Unpack a 16-bit signed integer + + 16-bit signed integer + + + + Unpack a 16-bit unsigned integer + + 16-bit unsigned integer + + + + Unpack a 32-bit signed integer + + 32-bit signed integer + + + + Unpack a 32-bit unsigned integer + + 32-bit unsigned integer + + + + + + + + + + Reads in a byte array of an Animation Asset created by the SecondLife(tm) client. + + + + + Rotation Keyframe count (used internally) + + + + + Position Keyframe count (used internally) + + + + + Animation Priority + + + + + The animation length in seconds. + + + + + Expression set in the client. Null if [None] is selected + + + + + The time in seconds to start the animation + + + + + The time in seconds to end the animation + + + + + Loop the animation + + + + + Meta data. Ease in Seconds. + + + + + Meta data. Ease out seconds. + + + + + Meta Data for the Hand Pose + + + + + Number of joints defined in the animation + + + + + Contains an array of joints + + + + + Searialize an animation asset into it's joints/keyframes/meta data + + + + + + Variable length strings seem to be null terminated in the animation asset.. but.. + use with caution, home grown. + advances the index. + + The animation asset byte array + The offset to start reading + a string + + + + Read in a Joint from an animation asset byte array + Variable length Joint fields, yay! + Advances the index + + animation asset byte array + Byte Offset of the start of the joint + The Joint data serialized into the binBVHJoint structure + + + + Read Keyframes of a certain type + advance i + + Animation Byte array + Offset in the Byte Array. Will be advanced + Number of Keyframes + Scaling Min to pass to the Uint16ToFloat method + Scaling Max to pass to the Uint16ToFloat method + + + + + Determines whether the specified is equal to the current . + + + true if the specified is equal to the current ; otherwise, false. + + The to compare with the current . + The parameter is null. + 2 + + + + Serves as a hash function for a particular type. + + + A hash code for the current . + + 2 + + + + A Joint and it's associated meta data and keyframes + + + + + Indicates whether this instance and a specified object are equal. + + + true if and this instance are the same type and represent the same value; otherwise, false. + + Another object to compare to. + 2 + + + + Returns the hash code for this instance. + + + A 32-bit signed integer that is the hash code for this instance. + + 2 + + + + Name of the Joint. Matches the avatar_skeleton.xml in client distros + + + + + Joint Animation Override? Was the same as the Priority in testing.. + + + + + Array of Rotation Keyframes in order from earliest to latest + + + + + Array of Position Keyframes in order from earliest to latest + This seems to only be for the Pelvis? + + + + + Custom application data that can be attached to a joint + + + + + A Joint Keyframe. This is either a position or a rotation. + + + + + Either a Vector3 position or a Vector3 Euler rotation + + + + + Poses set in the animation metadata for the hands. + + + + + Capabilities is the name of the bi-directional HTTP REST protocol + used to communicate non real-time transactions such as teleporting or + group messaging + + + + Reference to the simulator this system is connected to + + + + Default constructor + + + + + + + Request the URI of a named capability + + Name of the capability to request + The URI of the requested capability, or String.Empty if + the capability does not exist + + + + Process any incoming events, check to see if we have a message created for the event, + + + + + + Capabilities URI this system was initialized with + + + Whether the capabilities event queue is connected and + listening for incoming events + + + + Triggered when an event is received via the EventQueueGet + capability + + Event name + Decoded event data + The simulator that generated the event + + + + Attempts to convert an LLSD structure to a known Packet type + + Event name, this must match an actual + packet name for a Packet to be successfully built + LLSD to convert to a Packet + A Packet on success, otherwise null + + + + + + Looking direction, must be a normalized vector + Up direction, must be a normalized vector + + + + Align the coordinate frame X and Y axis with a given rotation + around the Z axis in radians + + Absolute rotation around the Z axis in + radians + + + Origin position of this coordinate frame + + + X axis of this coordinate frame, or Forward/At in grid terms + + + Y axis of this coordinate frame, or Left in grid terms + + + Z axis of this coordinate frame, or Up in grid terms + + + + Access to the data server which allows searching for land, events, people, etc + + + + The event subscribers. null if no subcribers + + + Raises the EventInfoReply event + An EventInfoReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the DirEventsReply event + An DirEventsReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the PlacesReply event + A PlacesReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the DirPlacesReply event + A DirPlacesReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the DirClassifiedsReply event + A DirClassifiedsReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the DirGroupsReply event + A DirGroupsReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the DirPeopleReply event + A DirPeopleReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the DirLandReply event + A DirLandReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + + Constructs a new instance of the DirectoryManager class + + An instance of GridClient + + + + Query the data server for a list of classified ads containing the specified string. + Defaults to searching for classified placed in any category, and includes PG, Adult and Mature + results. + + Responses are sent 16 per response packet, there is no way to know how many results a query reply will contain however assuming + the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received + + The event is raised when a response is received from the simulator + + A string containing a list of keywords to search for + A UUID to correlate the results when the event is raised + + + + Query the data server for a list of classified ads which contain specified keywords (Overload) + + The event is raised when a response is received from the simulator + + A string containing a list of keywords to search for + The category to search + A set of flags which can be ORed to modify query options + such as classified maturity rating. + A UUID to correlate the results when the event is raised + + Search classified ads containing the key words "foo" and "bar" in the "Any" category that are either PG or Mature + + UUID searchID = StartClassifiedSearch("foo bar", ClassifiedCategories.Any, ClassifiedQueryFlags.PG | ClassifiedQueryFlags.Mature); + + + + Responses are sent 16 at a time, there is no way to know how many results a query reply will contain however assuming + the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received + + + + + Starts search for places (Overloaded) + + The event is raised when a response is received from the simulator + + Search text + Each request is limited to 100 places + being returned. To get the first 100 result entries of a request use 0, + from 100-199 use 1, 200-299 use 2, etc. + A UUID to correlate the results when the event is raised + + + + Queries the dataserver for parcels of land which are flagged to be shown in search + + The event is raised when a response is received from the simulator + + A string containing a list of keywords to search for separated by a space character + A set of flags which can be ORed to modify query options + such as classified maturity rating. + The category to search + Each request is limited to 100 places + being returned. To get the first 100 result entries of a request use 0, + from 100-199 use 1, 200-299 use 2, etc. + A UUID to correlate the results when the event is raised + + Search places containing the key words "foo" and "bar" in the "Any" category that are either PG or Adult + + UUID searchID = StartDirPlacesSearch("foo bar", DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeAdult, ParcelCategory.Any, 0); + + + + Additional information on the results can be obtained by using the ParcelManager.InfoRequest method + + + + + Starts a search for land sales using the directory + + The event is raised when a response is received from the simulator + + What type of land to search for. Auction, + estate, mainland, "first land", etc + The OnDirLandReply event handler must be registered before + calling this function. There is no way to determine how many + results will be returned, or how many times the callback will be + fired other than you won't get more than 100 total parcels from + each query. + + + + Starts a search for land sales using the directory + + The event is raised when a response is received from the simulator + + What type of land to search for. Auction, + estate, mainland, "first land", etc + Maximum price to search for + Maximum area to search for + Each request is limited to 100 parcels + being returned. To get the first 100 parcels of a request use 0, + from 100-199 use 1, 200-299 use 2, etc. + The OnDirLandReply event handler must be registered before + calling this function. There is no way to determine how many + results will be returned, or how many times the callback will be + fired other than you won't get more than 100 total parcels from + each query. + + + + Send a request to the data server for land sales listings + + + Flags sent to specify query options + + Available flags: + Specify the parcel rating with one or more of the following: + IncludePG IncludeMature IncludeAdult + + Specify the field to pre sort the results with ONLY ONE of the following: + PerMeterSort NameSort AreaSort PricesSort + + Specify the order the results are returned in, if not specified the results are pre sorted in a Descending Order + SortAsc + + Specify additional filters to limit the results with one or both of the following: + LimitByPrice LimitByArea + + Flags can be combined by separating them with the | (pipe) character + + Additional details can be found in + + What type of land to search for. Auction, + Estate or Mainland + Maximum price to search for when the + DirFindFlags.LimitByPrice flag is specified in findFlags + Maximum area to search for when the + DirFindFlags.LimitByArea flag is specified in findFlags + Each request is limited to 100 parcels + being returned. To get the first 100 parcels of a request use 0, + from 100-199 use 100, 200-299 use 200, etc. + The event will be raised with the response from the simulator + + There is no way to determine how many results will be returned, or how many times the callback will be + fired other than you won't get more than 100 total parcels from + each reply. + + Any land set for sale to either anybody or specific to the connected agent will be included in the + results if the land is included in the query + + + // request all mainland, any maturity rating that is larger than 512 sq.m + StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByArea | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, SearchTypeFlags.Mainland, 0, 512, 0); + + + + + Search for Groups + + The name or portion of the name of the group you wish to search for + Start from the match number + + + + + Search for Groups + + The name or portion of the name of the group you wish to search for + Start from the match number + Search flags + + + + + Search the People directory for other avatars + + The name or portion of the name of the avatar you wish to search for + + + + + + Search Places for parcels of land you personally own + + + + + Searches Places for land owned by the specified group + + ID of the group you want to recieve land list for (You must be a member of the group) + Transaction (Query) ID which can be associated with results from your request. + + + + Search the Places directory for parcels that are listed in search and contain the specified keywords + + A string containing the keywords to search for + Transaction (Query) ID which can be associated with results from your request. + + + + Search Places - All Options + + One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc. + One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer + A string containing a list of keywords to search for separated by a space character + String Simulator Name to search in + LLUID of group you want to recieve results for + Transaction (Query) ID which can be associated with results from your request. + Transaction (Query) ID which can be associated with results from your request. + + + + Search All Events with specifid searchText in all categories, includes PG, Mature and Adult + + A string containing a list of keywords to search for separated by a space character + Each request is limited to 100 entries + being returned. To get the first group of entries of a request use 0, + from 100-199 use 100, 200-299 use 200, etc. + UUID of query to correlate results in callback. + + + + Search Events + + A string containing a list of keywords to search for separated by a space character + One or more of the following flags: DateEvents, IncludePG, IncludeMature, IncludeAdult + from the Enum + + Multiple flags can be combined by separating the flags with the | (pipe) character + "u" for in-progress and upcoming events, -or- number of days since/until event is scheduled + For example "0" = Today, "1" = tomorrow, "2" = following day, "-1" = yesterday, etc. + Each request is limited to 100 entries + being returned. To get the first group of entries of a request use 0, + from 100-199 use 100, 200-299 use 200, etc. + EventCategory event is listed under. + UUID of query to correlate results in callback. + + + Requests Event Details + ID of Event returned from the method + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming event message + The Unique Capabilities Key + The event message containing the data + The simulator the message originated from + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming event message + The Unique Capabilities Key + The event message containing the data + The simulator the message originated from + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Classified Ad categories + + + Classified is listed in the Any category + + + Classified is shopping related + + + Classified is + + + + + + + + + + + + + + + + + + + + + + + + Event Categories + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Query Flags used in many of the DirectoryManager methods to specify which query to execute and how to return the results. + + Flags can be combined using the | (pipe) character, not all flags are available in all queries + + + + Query the People database + + + + + + + + + Query the Groups database + + + Query the Events database + + + Query the land holdings database for land owned by the currently connected agent + + + + + + Query the land holdings database for land which is owned by a Group + + + Specifies the query should pre sort the results based upon traffic + when searching the Places database + + + + + + + + + + + + + + + Specifies the query should pre sort the results in an ascending order when searching the land sales database. + This flag is only used when searching the land sales database + + + Specifies the query should pre sort the results using the SalePrice field when searching the land sales database. + This flag is only used when searching the land sales database + + + Specifies the query should pre sort the results by calculating the average price/sq.m (SalePrice / Area) when searching the land sales database. + This flag is only used when searching the land sales database + + + Specifies the query should pre sort the results using the ParcelSize field when searching the land sales database. + This flag is only used when searching the land sales database + + + Specifies the query should pre sort the results using the Name field when searching the land sales database. + This flag is only used when searching the land sales database + + + When set, only parcels less than the specified Price will be included when searching the land sales database. + This flag is only used when searching the land sales database + + + When set, only parcels greater than the specified Size will be included when searching the land sales database. + This flag is only used when searching the land sales database + + + + + + + + + Include PG land in results. This flag is used when searching both the Groups, Events and Land sales databases + + + Include Mature land in results. This flag is used when searching both the Groups, Events and Land sales databases + + + Include Adult land in results. This flag is used when searching both the Groups, Events and Land sales databases + + + + + + + Land types to search dataserver for + + + + Search Auction, Mainland and Estate + + + Land which is currently up for auction + + + Parcels which are on the mainland (Linden owned) continents + + + Parcels which are on privately owned simulators + + + + The content rating of the event + + + + Event is PG + + + Event is Mature + + + Event is Adult + + + + Classified Ad Options + + There appear to be two formats the flags are packed in. + This set of flags is for the newer style + + + + + + + + + + + + + + + + + + + Classified ad query options + + + + Include all ads in results + + + Include PG ads in results + + + Include Mature ads in results + + + Include Adult ads in results + + + + The For Sale flag in PlacesReplyData + + + + Parcel is not listed for sale + + + Parcel is For Sale + + + + A classified ad on the grid + + + + UUID for this ad, useful for looking up detailed + information about it + + + The title of this classified ad + + + Flags that show certain options applied to the classified + + + Creation date of the ad + + + Expiration date of the ad + + + Price that was paid for this ad + + + Print the struct data as a string + A string containing the field name, and field value + + + + A parcel retrieved from the dataserver such as results from the + "For-Sale" listings or "Places" Search + + + + The unique dataserver parcel ID + This id is used to obtain additional information from the entry + by using the method + + + A string containing the name of the parcel + + + The size of the parcel + This field is not returned for Places searches + + + The price of the parcel + This field is not returned for Places searches + + + If True, this parcel is flagged to be auctioned + + + If true, this parcel is currently set for sale + + + Parcel traffic + + + Print the struct data as a string + A string containing the field name, and field value + + + + An Avatar returned from the dataserver + + + + Online status of agent + This field appears to be obsolete and always returns false + + + The agents first name + + + The agents last name + + + The agents + + + Print the struct data as a string + A string containing the field name, and field value + + + + Response to a "Groups" Search + + + + The Group ID + + + The name of the group + + + The current number of members + + + Print the struct data as a string + A string containing the field name, and field value + + + + Parcel information returned from a request + + Represents one of the following: + A parcel of land on the grid that has its Show In Search flag set + A parcel of land owned by the agent making the request + A parcel of land owned by a group the agent making the request is a member of + + + In a request for Group Land, the First record will contain an empty record + + Note: This is not the same as searching the land for sale data source + + + + The ID of the Agent of Group that owns the parcel + + + The name + + + The description + + + The Size of the parcel + + + The billable Size of the parcel, for mainland + parcels this will match the ActualArea field. For Group owned land this will be 10 percent smaller + than the ActualArea. For Estate land this will always be 0 + + + Indicates the ForSale status of the parcel + + + The Gridwide X position + + + The Gridwide Y position + + + The Z position of the parcel, or 0 if no landing point set + + + The name of the Region the parcel is located in + + + The Asset ID of the parcels Snapshot texture + + + The calculated visitor traffic + + + The billing product SKU + Known values are: + + 023Mainland / Full Region + 024Estate / Full Region + 027Estate / Openspace + 029Estate / Homestead + 129Mainland / Homestead (Linden Owned) + + + + + No longer used, will always be 0 + + + Get a SL URL for the parcel + A string, containing a standard SLURL + + + Print the struct data as a string + A string containing the field name, and field value + + + + An "Event" Listing summary + + + + The ID of the event creator + + + The name of the event + + + The events ID + + + A string containing the short date/time the event will begin + + + The event start time in Unixtime (seconds since epoch) + + + The events maturity rating + + + Print the struct data as a string + A string containing the field name, and field value + + + + The details of an "Event" + + + + The events ID + + + The ID of the event creator + + + The name of the event + + + The category + + + The events description + + + The short date/time the event will begin + + + The event start time in Unixtime (seconds since epoch) UTC adjusted + + + The length of the event in minutes + + + 0 if no cover charge applies + + + The cover charge amount in L$ if applicable + + + The name of the region where the event is being held + + + The gridwide location of the event + + + The maturity rating + + + Get a SL URL for the parcel where the event is hosted + A string, containing a standard SLURL + + + Print the struct data as a string + A string containing the field name, and field value + + + Contains the Event data returned from the data server from an EventInfoRequest + + + Construct a new instance of the EventInfoReplyEventArgs class + A single EventInfo object containing the details of an event + + + + A single EventInfo object containing the details of an event + + + + Contains the "Event" detail data returned from the data server + + + Construct a new instance of the DirEventsReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list containing the "Events" returned by the search query + + + The ID returned by + + + A list of "Events" returned by the data server + + + Contains the "Event" list data returned from the data server + + + Construct a new instance of PlacesReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list containing the "Places" returned by the data server query + + + The ID returned by + + + A list of "Places" returned by the data server + + + Contains the places data returned from the data server + + + Construct a new instance of the DirPlacesReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list containing land data returned by the data server + + + The ID returned by + + + A list containing Places data returned by the data server + + + Contains the classified data returned from the data server + + + Construct a new instance of the DirClassifiedsReplyEventArgs class + A list of classified ad data returned from the data server + + + A list containing Classified Ads returned by the data server + + + Contains the group data returned from the data server + + + Construct a new instance of the DirGroupsReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list of groups data returned by the data server + + + The ID returned by + + + A list containing Groups data returned by the data server + + + Contains the people data returned from the data server + + + Construct a new instance of the DirPeopleReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list of people data returned by the data server + + + The ID returned by + + + A list containing People data returned by the data server + + + Contains the land sales data returned from the data server + + + Construct a new instance of the DirLandReplyEventArgs class + A list of parcels for sale returned by the data server + + + A list containing land forsale data returned by the data server + + + + Represends individual HTTP Download request + + + + URI of the item to fetch + + + Timout specified in milliseconds + + + Download progress callback + + + Download completed callback + + + Accept the following content type + + + How many times will this request be retried + + + Current fetch attempt + + + Default constructor + + + Constructor + + + + Manages async HTTP downloads with a limit on maximum + concurrent downloads + + + + Default constructor + + + Cleanup method + + + Setup http download request + + + Check the queue for pending work + + + Enqueue a new HTTP download + + + Maximum number of parallel downloads from a single endpoint + + + Client certificate + + + Describes tasks returned in LandStatReply + + + + Estate level administration and utilities + + + + Textures for each of the four terrain height levels + + + Upper/lower texture boundaries for each corner of the sim + + + + Constructor for EstateTools class + + + + + The event subscribers. null if no subcribers + + + Raises the TopCollidersReply event + A TopCollidersReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the TopScriptsReply event + A TopScriptsReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the EstateUsersReply event + A EstateUsersReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the EstateGroupsReply event + A EstateGroupsReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the EstateManagersReply event + A EstateManagersReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the EstateBansReply event + A EstateBansReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the EstateCovenantReply event + A EstateCovenantReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the EstateUpdateInfoReply event + A EstateUpdateInfoReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + + Requests estate information such as top scripts and colliders + + + + + + + + Requests estate settings, including estate manager and access/ban lists + + + Requests the "Top Scripts" list for the current region + + + Requests the "Top Colliders" list for the current region + + + + Set several estate specific configuration variables + + The Height of the waterlevel over the entire estate. Defaults to 20 + The maximum height change allowed above the baked terrain. Defaults to 4 + The minimum height change allowed below the baked terrain. Defaults to -4 + true to use + if True forces the sun position to the position in SunPosition + The current position of the sun on the estate, or when FixedSun is true the static position + the sun will remain. 6.0 = Sunrise, 30.0 = Sunset + + + + Request return of objects owned by specified avatar + + The Agents owning the primitives to return + specify the coverage and type of objects to be included in the return + true to perform return on entire estate + + + + + + + + + Used for setting and retrieving various estate panel settings + + EstateOwnerMessage Method field + List of parameters to include + + + + Kick an avatar from an estate + + Key of Agent to remove + + + + Ban an avatar from an estate + Key of Agent to remove + Ban user from this estate and all others owned by the estate owner + + + Unban an avatar from an estate + Key of Agent to remove + /// Unban user from this estate and all others owned by the estate owner + + + + Send a message dialog to everyone in an entire estate + + Message to send all users in the estate + + + + Send a message dialog to everyone in a simulator + + Message to send all users in the simulator + + + + Send an avatar back to their home location + + Key of avatar to send home + + + + Begin the region restart process + + + + + Cancels a region restart + + + + Estate panel "Region" tab settings + + + Estate panel "Debug" tab settings + + + Used for setting the region's terrain textures for its four height levels + + + + + + + Used for setting sim terrain texture heights + + + Requests the estate covenant + + + + Upload a terrain RAW file + + A byte array containing the encoded terrain data + The name of the file being uploaded + The Id of the transfer request + + + + Teleports all users home in current Estate + + + + + Remove estate manager + Key of Agent to Remove + removes manager to this estate and all others owned by the estate owner + + + + Add estate manager + Key of Agent to Add + Add agent as manager to this estate and all others owned by the estate owner + + + + Add's an agent to the estate Allowed list + Key of Agent to Add + Add agent as an allowed reisdent to All estates if true + + + + Removes an agent from the estate Allowed list + Key of Agent to Remove + Removes agent as an allowed reisdent from All estates if true + + + + + Add's a group to the estate Allowed list + Key of Group to Add + Add Group as an allowed group to All estates if true + + + + + Removes a group from the estate Allowed list + Key of Group to Remove + Removes Group as an allowed Group from All estates if true + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Raised when the data server responds to a request. + + + Used in the ReportType field of a LandStatRequest + + + Used by EstateOwnerMessage packets + + + Used by EstateOwnerMessage packets + + + + + + + + No flags set + + + Only return targets scripted objects + + + Only return targets objects if on others land + + + Returns target's scripted objects and objects on other parcels + + + Ground texture settings for each corner of the region + + + Used by GroundTextureHeightSettings + + + The high and low texture thresholds for each corner of the sim + + + Raised on LandStatReply when the report type is for "top colliders" + + + Construct a new instance of the TopCollidersReplyEventArgs class + The number of returned items in LandStatReply + Dictionary of Object UUIDs to tasks returned in LandStatReply + + + + The number of returned items in LandStatReply + + + + + A Dictionary of Object UUIDs to tasks returned in LandStatReply + + + + Raised on LandStatReply when the report type is for "top Scripts" + + + Construct a new instance of the TopScriptsReplyEventArgs class + The number of returned items in LandStatReply + Dictionary of Object UUIDs to tasks returned in LandStatReply + + + + The number of scripts returned in LandStatReply + + + + + A Dictionary of Object UUIDs to tasks returned in LandStatReply + + + + Returned, along with other info, upon a successful .RequestInfo() + + + Construct a new instance of the EstateBansReplyEventArgs class + The estate's identifier on the grid + The number of returned items in LandStatReply + User UUIDs banned + + + + The identifier of the estate + + + + + The number of returned itmes + + + + + List of UUIDs of Banned Users + + + + Returned, along with other info, upon a successful .RequestInfo() + + + Construct a new instance of the EstateUsersReplyEventArgs class + The estate's identifier on the grid + The number of users + Allowed users UUIDs + + + + The identifier of the estate + + + + + The number of returned items + + + + + List of UUIDs of Allowed Users + + + + Returned, along with other info, upon a successful .RequestInfo() + + + Construct a new instance of the EstateGroupsReplyEventArgs class + The estate's identifier on the grid + The number of Groups + Allowed Groups UUIDs + + + + The identifier of the estate + + + + + The number of returned items + + + + + List of UUIDs of Allowed Groups + + + + Returned, along with other info, upon a successful .RequestInfo() + + + Construct a new instance of the EstateManagersReplyEventArgs class + The estate's identifier on the grid + The number of Managers + Managers UUIDs + + + + The identifier of the estate + + + + + The number of returned items + + + + + List of UUIDs of the Estate's Managers + + + + Returned, along with other info, upon a successful .RequestInfo() + + + Construct a new instance of the EstateCovenantReplyEventArgs class + The Covenant ID + The timestamp + The estate's name + The Estate Owner's ID (can be a GroupID) + + + + The Covenant + + + + + The timestamp + + + + + The Estate name + + + + + The Estate Owner's ID (can be a GroupID) + + + + Returned, along with other info, upon a successful .RequestInfo() + + + Construct a new instance of the EstateUpdateInfoReplyEventArgs class + The estate's name + The Estate Owners ID (can be a GroupID) + The estate's identifier on the grid + + + + + The estate's name + + + + + The Estate Owner's ID (can be a GroupID) + + + + + The identifier of the estate on the grid + + + + + + + + Registers, unregisters, and fires events generated by incoming packets + + + + Reference to the GridClient object + + + + Default constructor + + + + + + Register an event handler + + Use PacketType.Default to fire this event on every + incoming packet + Packet type to register the handler for + Callback to be fired + True if this callback should be ran + asynchronously, false to run it synchronous + + + + Unregister an event handler + + Packet type to unregister the handler for + Callback to be unregistered + + + + Fire the events registered for this packet type + + Incoming packet type + Incoming packet + Simulator this packet was received from + + + + Object that is passed to worker threads in the ThreadPool for + firing packet callbacks + + + + Callback to fire for this packet + + + Reference to the simulator that this packet came from + + + The packet that needs to be processed + + + + Registers, unregisters, and fires events generated by the Capabilities + event queue + + + + Reference to the GridClient object + + + + Default constructor + + Reference to the GridClient object + + + + Register an new event handler for a capabilities event sent via the EventQueue + + Use String.Empty to fire this event on every CAPS event + Capability event name to register the + handler for + Callback to fire + + + + Unregister a previously registered capabilities handler + + Capability event name unregister the + handler for + Callback to unregister + + + + Fire the events registered for this event type synchronously + + Capability name + Decoded event body + Reference to the simulator that + generated this event + + + + Fire the events registered for this event type asynchronously + + Capability name + Decoded event body + Reference to the simulator that + generated this event + + + + Object that is passed to worker threads in the ThreadPool for + firing CAPS callbacks + + + + Callback to fire for this packet + + + Name of the CAPS event + + + Strongly typed decoded data + + + Reference to the simulator that generated this event + + + + + + + + The avatar has no rights + + + The avatar can see the online status of the target avatar + + + The avatar can see the location of the target avatar on the map + + + The avatar can modify the ojects of the target avatar + + + + This class holds information about an avatar in the friends list. There are two ways + to interface to this class. The first is through the set of boolean properties. This is the typical + way clients of this class will use it. The second interface is through two bitflag properties, + TheirFriendsRights and MyFriendsRights + + + + + Used internally when building the initial list of friends at login time + + System ID of the avatar being prepesented + Rights the friend has to see you online and to modify your objects + Rights you have to see your friend online and to modify their objects + + + + FriendInfo represented as a string + + A string reprentation of both my rights and my friends rights + + + + System ID of the avatar + + + + + full name of the avatar + + + + + True if the avatar is online + + + + + True if the friend can see if I am online + + + + + True if the friend can see me on the map + + + + + True if the freind can modify my objects + + + + + True if I can see if my friend is online + + + + + True if I can see if my friend is on the map + + + + + True if I can modify my friend's objects + + + + + My friend's rights represented as bitmapped flags + + + + + My rights represented as bitmapped flags + + + + + This class is used to add and remove avatars from your friends list and to manage their permission. + + + + The event subscribers. null if no subcribers + + + Raises the FriendOnline event + A FriendInfoEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the FriendOffline event + A FriendInfoEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the FriendRightsUpdate event + A FriendInfoEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the FriendNames event + A FriendNamesEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the FriendshipOffered event + A FriendshipOfferedEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the FriendshipResponse event + A FriendshipResponseEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the FriendshipTerminated event + A FriendshipTerminatedEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the FriendFoundReply event + A FriendFoundReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + + A dictionary of key/value pairs containing known friends of this avatar. + + The Key is the of the friend, the value is a + object that contains detailed information including permissions you have and have given to the friend + + + + + A Dictionary of key/value pairs containing current pending frienship offers. + + The key is the of the avatar making the request, + the value is the of the request which is used to accept + or decline the friendship offer + + + + + Internal constructor + + A reference to the GridClient Object + + + + Accept a friendship request + + agentID of avatatar to form friendship with + imSessionID of the friendship request message + + + + Decline a friendship request + + of friend + imSessionID of the friendship request message + + + + Overload: Offer friendship to an avatar. + + System ID of the avatar you are offering friendship to + + + + Offer friendship to an avatar. + + System ID of the avatar you are offering friendship to + A message to send with the request + + + + Terminate a friendship with an avatar + + System ID of the avatar you are terminating the friendship with + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + + Change the rights of a friend avatar. + + the of the friend + the new rights to give the friend + This method will implicitly set the rights to those passed in the rights parameter. + + + + Use to map a friends location on the grid. + + Friends UUID to find + + + + + Use to track a friends movement on the grid + + Friends Key + + + + Ask for a notification of friend's online status + + Friend's UUID + + + + This handles the asynchronous response of a RequestAvatarNames call. + + + names cooresponding to the the list of IDs sent the the RequestAvatarNames call. + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + + Populate FriendList with data from the login reply + + true if login was successful + true if login request is requiring a redirect + A string containing the response to the login request + A string containing the reason for the request + A object containing the decoded + reply from the login server + + + Raised when the simulator sends notification one of the members in our friends list comes online + + + Raised when the simulator sends notification one of the members in our friends list goes offline + + + Raised when the simulator sends notification one of the members in our friends list grants or revokes permissions + + + Raised when the simulator sends us the names on our friends list + + + Raised when the simulator sends notification another agent is offering us friendship + + + Raised when a request we sent to friend another agent is accepted or declined + + + Raised when the simulator sends notification one of the members in our friends list has terminated + our friendship + + + Raised when the simulator sends the location of a friend we have + requested map location info for + + + Contains information on a member of our friends list + + + + Construct a new instance of the FriendInfoEventArgs class + + The FriendInfo + + + Get the FriendInfo + + + Contains Friend Names + + + + Construct a new instance of the FriendNamesEventArgs class + + A dictionary where the Key is the ID of the Agent, + and the Value is a string containing their name + + + A dictionary where the Key is the ID of the Agent, + and the Value is a string containing their name + + + Sent when another agent requests a friendship with our agent + + + + Construct a new instance of the FriendshipOfferedEventArgs class + + The ID of the agent requesting friendship + The name of the agent requesting friendship + The ID of the session, used in accepting or declining the + friendship offer + + + Get the ID of the agent requesting friendship + + + Get the name of the agent requesting friendship + + + Get the ID of the session, used in accepting or declining the + friendship offer + + + A response containing the results of our request to form a friendship with another agent + + + + Construct a new instance of the FriendShipResponseEventArgs class + + The ID of the agent we requested a friendship with + The name of the agent we requested a friendship with + true if the agent accepted our friendship offer + + + Get the ID of the agent we requested a friendship with + + + Get the name of the agent we requested a friendship with + + + true if the agent accepted our friendship offer + + + Contains data sent when a friend terminates a friendship with us + + + + Construct a new instance of the FrindshipTerminatedEventArgs class + + The ID of the friend who terminated the friendship with us + The name of the friend who terminated the friendship with us + + + Get the ID of the agent that terminated the friendship with us + + + Get the name of the agent that terminated the friendship with us + + + + Data sent in response to a request which contains the information to allow us to map the friends location + + + + + Construct a new instance of the FriendFoundReplyEventArgs class + + The ID of the agent we have requested location information for + The region handle where our friend is located + The simulator local position our friend is located + + + Get the ID of the agent we have received location information for + + + Get the region handle where our mapped friend is located + + + Get the simulator local position where our friend is located + + + + Main class to expose grid functionality to clients. All of the + classes needed for sending and receiving data are accessible through + this class. + + + + // Example minimum code required to instantiate class and + // connect to a simulator. + using System; + using System.Collections.Generic; + using System.Text; + using OpenMetaverse; + + namespace FirstBot + { + class Bot + { + public static GridClient Client; + static void Main(string[] args) + { + Client = new GridClient(); // instantiates the GridClient class + // to the global Client object + // Login to Simulator + Client.Network.Login("FirstName", "LastName", "Password", "FirstBot", "1.0"); + // Wait for a Keypress + Console.ReadLine(); + // Logout of simulator + Client.Network.Logout(); + } + } + } + + + + + Networking subsystem + + + Settings class including constant values and changeable + parameters for everything + + + Parcel (subdivided simulator lots) subsystem + + + Our own avatars subsystem + + + Other avatars subsystem + + + Estate subsystem + + + Friends list subsystem + + + Grid (aka simulator group) subsystem + + + Object subsystem + + + Group subsystem + + + Asset subsystem + + + Appearance subsystem + + + Inventory subsystem + + + Directory searches including classifieds, people, land + sales, etc + + + Handles land, wind, and cloud heightmaps + + + Handles sound-related networking + + + Throttling total bandwidth usage, or allocating bandwidth + for specific data stream types + + + + Default constructor + + + + + Return the full name of this instance + + Client avatars full name + + + + Map layer request type + + + + Objects and terrain are shown + + + Only the terrain is shown, no objects + + + Overlay showing land for sale and for auction + + + + Type of grid item, such as telehub, event, populator location, etc. + + + + Telehub + + + PG rated event + + + Mature rated event + + + Popular location + + + Locations of avatar groups in a region + + + Land for sale + + + Classified ad + + + Adult rated event + + + Adult land for sale + + + + Information about a region on the grid map + + + + Sim X position on World Map + + + Sim Y position on World Map + + + Sim Name (NOTE: In lowercase!) + + + + + + Appears to always be zero (None) + + + Sim's defined Water Height + + + + + + UUID of the World Map image + + + Unique identifier for this region, a combination of the X + and Y position + + + + + + + + + + + + + + + + + + + + + + + Visual chunk of the grid map + + + + + Base class for Map Items + + + + The Global X position of the item + + + The Global Y position of the item + + + Get the Local X position of the item + + + Get the Local Y position of the item + + + Get the Handle of the region + + + + Represents an agent or group of agents location + + + + + Represents a Telehub location + + + + + Represents a non-adult parcel of land for sale + + + + + Represents an Adult parcel of land for sale + + + + + Represents a PG Event + + + + + Represents a Mature event + + + + + Represents an Adult event + + + + + Manages grid-wide tasks such as the world map + + + + The event subscribers. null if no subcribers + + + Raises the CoarseLocationUpdate event + A CoarseLocationUpdateEventArgs object containing the + data sent by simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GridRegion event + A GridRegionEventArgs object containing the + data sent by simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GridLayer event + A GridLayerEventArgs object containing the + data sent by simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GridItems event + A GridItemEventArgs object containing the + data sent by simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the RegionHandleReply event + A RegionHandleReplyEventArgs object containing the + data sent by simulator + + + Thread sync lock object + + + A dictionary of all the regions, indexed by region name + + + A dictionary of all the regions, indexed by region handle + + + + Constructor + + Instance of GridClient object to associate with this GridManager instance + + + + + + + + + + Request a map layer + + The name of the region + The type of layer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Request data for all mainland (Linden managed) simulators + + + + + Request the region handle for the specified region UUID + + UUID of the region to look up + + + + Get grid region information using the region name, this function + will block until it can find the region or gives up + + Name of sim you're looking for + Layer that you are requesting + Will contain a GridRegion for the sim you're + looking for if successful, otherwise an empty structure + True if the GridRegion was successfully fetched, otherwise + false + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Raised when the simulator sends a + containing the location of agents in the simulator + + + Raised when the simulator sends a Region Data in response to + a Map request + + + Raised when the simulator sends GridLayer object containing + a map tile coordinates and texture information + + + Raised when the simulator sends GridItems object containing + details on events, land sales at a specific location + + + Raised in response to a Region lookup + + + Unknown + + + Current direction of the sun + + + Current angular velocity of the sun + + + Microseconds since the start of SL 4-hour day + + + + Avatar group management + + + + Key of Group Member + + + Total land contribution + + + Online status information + + + Abilities that the Group Member has + + + Current group title + + + Is a group owner + + + + Role manager for a group + + + + Key of the group + + + Key of Role + + + Name of Role + + + Group Title associated with Role + + + Description of Role + + + Abilities Associated with Role + + + Returns the role's title + The role's title + + + + Class to represent Group Title + + + + Key of the group + + + ID of the role title belongs to + + + Group Title + + + Whether title is Active + + + Returns group title + + + + Represents a group on the grid + + + + Key of Group + + + Key of Group Insignia + + + Key of Group Founder + + + Key of Group Role for Owners + + + Name of Group + + + Text of Group Charter + + + Title of "everyone" role + + + Is the group open for enrolement to everyone + + + Will group show up in search + + + + + + + + + + + + Is the group Mature + + + Cost of group membership + + + + + + + + + The total number of current members this group has + + + The number of roles this group has configured + + + Show this group in agent's profile + + + Returns the name of the group + A string containing the name of the group + + + + A group Vote + + + + Key of Avatar who created Vote + + + Text of the Vote proposal + + + Total number of votes + + + + A group proposal + + + + The Text of the proposal + + + The minimum number of members that must vote before proposal passes or failes + + + The required ration of yes/no votes required for vote to pass + The three options are Simple Majority, 2/3 Majority, and Unanimous + TODO: this should be an enum + + + The duration in days votes are accepted + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Struct representing a group notice + + + + + + + + + + + + + + + + + + + + + + + Struct representing a group notice list entry + + + + Notice ID + + + Creation timestamp of notice + + + Agent name who created notice + + + Notice subject + + + Is there an attachment? + + + Attachment Type + + + + Struct representing a member of a group chat session and their settings + + + + The of the Avatar + + + True if user has voice chat enabled + + + True of Avatar has moderator abilities + + + True if a moderator has muted this avatars chat + + + True if a moderator has muted this avatars voice + + + + Role update flags + + + + + + + + + + + + + + + + + + + + + + + + + Can send invitations to groups default role + + + Can eject members from group + + + Can toggle 'Open Enrollment' and change 'Signup fee' + + + Member is visible in the public member list + + + Can create new roles + + + Can delete existing roles + + + Can change Role names, titles and descriptions + + + Can assign other members to assigners role + + + Can assign other members to any role + + + Can remove members from roles + + + Can assign and remove abilities in roles + + + Can change group Charter, Insignia, 'Publish on the web' and which + members are publicly visible in group member listings + + + Can buy land or deed land to group + + + Can abandon group owned land to Governor Linden on mainland, or Estate owner for + private estates + + + Can set land for-sale information on group owned parcels + + + Can subdivide and join parcels + + + Can join group chat sessions + + + Can use voice chat in Group Chat sessions + + + Can moderate group chat sessions + + + Can toggle "Show in Find Places" and set search category + + + Can change parcel name, description, and 'Publish on web' settings + + + Can set the landing point and teleport routing on group land + + + Can change music and media settings + + + Can toggle 'Edit Terrain' option in Land settings + + + Can toggle various About Land > Options settings + + + Can always terraform land, even if parcel settings have it turned off + + + Can always fly while over group owned land + + + Can always rez objects on group owned land + + + Can always create landmarks for group owned parcels + + + Can set home location on any group owned parcel + + + Can modify public access settings for group owned parcels + + + Can manager parcel ban lists on group owned land + + + Can manage pass list sales information + + + Can eject and freeze other avatars on group owned land + + + Can return objects set to group + + + Can return non-group owned/set objects + + + Can return group owned objects + + + Can landscape using Linden plants + + + Can deed objects to group + + + Can move group owned objects + + + Can set group owned objects for-sale + + + Pay group liabilities and receive group dividends + + + List and Host group events + + + Can send group notices + + + Can receive group notices + + + Can create group proposals + + + Can vote on group proposals + + + + Ban actions available for group members + + + + Ban agent from joining a group + + + Remove restriction on agent jointing a group + + + + Handles all network traffic related to reading and writing group + information + + + + The event subscribers. null if no subcribers + + + Raises the CurrentGroups event + A CurrentGroupsEventArgs object containing the + data sent from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupNamesReply event + A GroupNamesEventArgs object containing the + data response from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupProfile event + An GroupProfileEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupMembers event + A GroupMembersEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupRolesDataReply event + A GroupRolesDataReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupRoleMembersReply event + A GroupRolesRoleMembersReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupTitlesReply event + A GroupTitlesReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupAccountSummary event + A GroupAccountSummaryReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupCreated event + An GroupCreatedEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupJoined event + A GroupOperationEventArgs object containing the + result of the operation returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupLeft event + A GroupOperationEventArgs object containing the + result of the operation returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupDropped event + An GroupDroppedEventArgs object containing the + the group your agent left + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupMemberEjected event + An GroupMemberEjectedEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupNoticesListReply event + An GroupNoticesListReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the GroupInvitation event + An GroupInvitationEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the BannedAgents event + An BannedAgentsEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + A reference to the current instance + + + Currently-active group members requests + + + Currently-active group roles requests + + + Currently-active group role-member requests + + + Dictionary keeping group members while request is in progress + + + Dictionary keeping mebmer/role mapping while request is in progress + + + Dictionary keeping GroupRole information while request is in progress + + + Caches group name lookups + + + + Construct a new instance of the GroupManager class + + A reference to the current instance + + + + Request a current list of groups the avatar is a member of. + + CAPS Event Queue must be running for this to work since the results + come across CAPS. + + + + Lookup name of group based on groupID + + groupID of group to lookup name for. + + + + Request lookup of multiple group names + + List of group IDs to request. + + + Lookup group profile data such as name, enrollment, founder, logo, etc + Subscribe to OnGroupProfile event to receive the results. + group ID (UUID) + + + Request a list of group members. + Subscribe to OnGroupMembers event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache + + + Request group roles + Subscribe to OnGroupRoles event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache + + + Request members (members,role) role mapping for a group. + Subscribe to OnGroupRolesMembers event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache + + + Request a groups Titles + Subscribe to OnGroupTitles event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache + + + Begin to get the group account summary + Subscribe to the OnGroupAccountSummary event to receive the results. + group ID (UUID) + How long of an interval + Which interval (0 for current, 1 for last) + + + Invites a user to a group + The group to invite to + A list of roles to invite a person to + Key of person to invite + + + Set a group as the current active group + group ID (UUID) + + + Change the role that determines your active title + Group ID to use + Role ID to change to + + + Set this avatar's tier contribution + Group ID to change tier in + amount of tier to donate + + + + Save wheather agent wants to accept group notices and list this group in their profile + + Group + Accept notices from this group + List this group in the profile + + + Request to join a group + Subscribe to OnGroupJoined event for confirmation. + group ID (UUID) to join. + + + + Request to create a new group. If the group is successfully + created, L$100 will automatically be deducted + + Subscribe to OnGroupCreated event to receive confirmation. + Group struct containing the new group info + + + Update a group's profile and other information + Groups ID (UUID) to update. + Group struct to update. + + + Eject a user from a group + Group ID to eject the user from + Avatar's key to eject + + + Update role information + Modified role to be updated + + + Create a new group role + Group ID to update + Role to create + + + Delete a group role + Group ID to update + Role to delete + + + Remove an avatar from a role + Group ID to update + Role ID to be removed from + Avatar's Key to remove + + + Assign an avatar to a role + Group ID to update + Role ID to assign to + Avatar's ID to assign to role + + + Request the group notices list + Group ID to fetch notices for + + + Request a group notice by key + ID of group notice + + + Send out a group notice + Group ID to update + GroupNotice structure containing notice data + + + Start a group proposal (vote) + The Group ID to send proposal to + GroupProposal structure containing the proposal + + + Request to leave a group + Subscribe to OnGroupLeft event to receive confirmation + The group to leave + + + + Gets the URI of the cpability for handling group bans + + Group ID + null, if the feature is not supported, or URI of the capability + + + + Request a list of residents banned from joining a group + + UUID of the group + + + + Request a list of residents banned from joining a group + + UUID of the group + Callback on request completition + + + + Request that group of agents be banned or unbanned from the group + + Group ID + Ban/Unban action + Array of agents UUIDs to ban + + + + Request that group of agents be banned or unbanned from the group + + Group ID + Ban/Unban action + Array of agents UUIDs to ban + Callback + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Raised when the simulator sends us data containing + our current group membership + + + Raised when the simulator responds to a RequestGroupName + or RequestGroupNames request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when a response to a RequestGroupAccountSummary is returned + by the simulator + + + Raised when a request to create a group is successful + + + Raised when a request to join a group either + fails or succeeds + + + Raised when a request to leave a group either + fails or succeeds + + + Raised when A group is removed from the group server + + + Raised when a request to eject a member from a group either + fails or succeeds + + + Raised when the simulator sends us group notices + + + + Raised when another agent invites our avatar to join a group + + + Raised when another agent invites our avatar to join a group + + + Contains the current groups your agent is a member of + + + Construct a new instance of the CurrentGroupsEventArgs class + The current groups your agent is a member of + + + Get the current groups your agent is a member of + + + A Dictionary of group names, where the Key is the groups ID and the value is the groups name + + + Construct a new instance of the GroupNamesEventArgs class + The Group names dictionary + + + Get the Group Names dictionary + + + Represents the members of a group + + + + Construct a new instance of the GroupMembersReplyEventArgs class + + The ID of the request + The ID of the group + The membership list of the group + + + Get the ID as returned by the request to correlate + this result set and the request + + + Get the ID of the group + + + Get the dictionary of members + + + Represents the roles associated with a group + + + Construct a new instance of the GroupRolesDataReplyEventArgs class + The ID as returned by the request to correlate + this result set and the request + The ID of the group + The dictionary containing the roles + + + Get the ID as returned by the request to correlate + this result set and the request + + + Get the ID of the group + + + Get the dictionary containing the roles + + + Represents the Role to Member mappings for a group + + + Construct a new instance of the GroupRolesMembersReplyEventArgs class + The ID as returned by the request to correlate + this result set and the request + The ID of the group + The member to roles map + + + Get the ID as returned by the request to correlate + this result set and the request + + + Get the ID of the group + + + Get the member to roles map + + + Represents the titles for a group + + + Construct a new instance of the GroupTitlesReplyEventArgs class + The ID as returned by the request to correlate + this result set and the request + The ID of the group + The titles + + + Get the ID as returned by the request to correlate + this result set and the request + + + Get the ID of the group + + + Get the titles + + + Represents the summary data for a group + + + Construct a new instance of the GroupAccountSummaryReplyEventArgs class + The ID of the group + The summary data + + + Get the ID of the group + + + Get the summary data + + + A response to a group create request + + + Construct a new instance of the GroupCreatedReplyEventArgs class + The ID of the group + the success or faulure of the request + A string containing additional information + + + Get the ID of the group + + + true of the group was created successfully + + + A string containing the message + + + Represents a response to a request + + + Construct a new instance of the GroupOperationEventArgs class + The ID of the group + true of the request was successful + + + Get the ID of the group + + + true of the request was successful + + + Represents your agent leaving a group + + + Construct a new instance of the GroupDroppedEventArgs class + The ID of the group + + + Get the ID of the group + + + Represents a list of active group notices + + + Construct a new instance of the GroupNoticesListReplyEventArgs class + The ID of the group + The list containing active notices + + + Get the ID of the group + + + Get the notices list + + + Represents the profile of a group + + + Construct a new instance of the GroupProfileEventArgs class + The group profile + + + Get the group profile + + + + Provides notification of a group invitation request sent by another Avatar + + The invitation is raised when another avatar makes an offer for our avatar + to join a group. + + + The ID of the Avatar sending the group invitation + + + The name of the Avatar sending the group invitation + + + A message containing the request information which includes + the name of the group, the groups charter and the fee to join details + + + The Simulator + + + Set to true to accept invitation, false to decline + + + + Result of the request for list of agents banned from a group + + + + Indicates if list of banned agents for a group was successfully retrieved + + + Indicates if list of banned agents for a group was successfully retrieved + + + Array containing a list of UUIDs of the agents banned from a group + + + + Static helper functions and global variables + + + + This header flag signals that ACKs are appended to the packet + + + This header flag signals that this packet has been sent before + + + This header flags signals that an ACK is expected for this packet + + + This header flag signals that the message is compressed using zerocoding + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Given an X/Y location in absolute (grid-relative) terms, a region + handle is returned along with the local X/Y location in that region + + The absolute X location, a number such as + 255360.35 + The absolute Y location, a number such as + 255360.35 + The sim-local X position of the global X + position, a value from 0.0 to 256.0 + The sim-local Y position of the global Y + position, a value from 0.0 to 256.0 + A 64-bit region handle that can be used to teleport to + + + + Converts a floating point number to a terse string format used for + transmitting numbers in wearable asset files + + Floating point number to convert to a string + A terse string representation of the input number + + + + Convert a variable length field (byte array) to a string, with a + field name prepended to each line of the output + + If the byte array has unprintable characters in it, a + hex dump will be written instead + The StringBuilder object to write to + The byte array to convert to a string + A field name to prepend to each line of output + + + + Decode a zerocoded byte array, used to decompress packets marked + with the zerocoded flag + + Any time a zero is encountered, the next byte is a count + of how many zeroes to expand. One zero is encoded with 0x00 0x01, + two zeroes is 0x00 0x02, three zeroes is 0x00 0x03, etc. The + first four bytes are copied directly to the output buffer. + + The byte array to decode + The length of the byte array to decode. This + would be the length of the packet up to (but not including) any + appended ACKs + The output byte array to decode to + The length of the output buffer + + + + Encode a byte array with zerocoding. Used to compress packets marked + with the zerocoded flag. Any zeroes in the array are compressed down + to a single zero byte followed by a count of how many zeroes to expand + out. A single zero becomes 0x00 0x01, two zeroes becomes 0x00 0x02, + three zeroes becomes 0x00 0x03, etc. The first four bytes are copied + directly to the output buffer. + + The byte array to encode + The length of the byte array to encode + The output byte array to encode to + The length of the output buffer + + + + Calculates the CRC (cyclic redundancy check) needed to upload inventory. + + Creation date + Sale type + Inventory type + Type + Asset ID + Group ID + Sale price + Owner ID + Creator ID + Item ID + Folder ID + Everyone mask (permissions) + Flags + Next owner mask (permissions) + Group mask (permissions) + Owner mask (permissions) + The calculated CRC + + + + Attempts to load a file embedded in the assembly + + The filename of the resource to load + A Stream for the requested file, or null if the resource + was not successfully loaded + + + + Attempts to load a file either embedded in the assembly or found in + a given search path + + The filename of the resource to load + An optional path that will be searched if + the asset is not found embedded in the assembly + A Stream for the requested file, or null if the resource + was not successfully loaded + + + + Converts a list of primitives to an object that can be serialized + with the LLSD system + + Primitives to convert to a serializable object + An object that can be serialized with LLSD + + + + Deserializes OSD in to a list of primitives + + Structure holding the serialized primitive list, + must be of the SDMap type + A list of deserialized primitives + + + + Converts a struct or class object containing fields only into a key value separated string + + The struct object + A string containing the struct fields as the keys, and the field value as the value separated + + + // Add the following code to any struct or class containing only fields to override the ToString() + // method to display the values of the passed object + + /// Print the struct data as a string + ///A string containing the field name, and field value + public override string ToString() + { + return Helpers.StructToString(this); + } + + + + + + Passed to Logger.Log() to identify the severity of a log entry + + + + No logging information will be output + + + Non-noisy useful information, may be helpful in + debugging a problem + + + A non-critical error occurred. A warning will not + prevent the rest of the library from operating as usual, + although it may be indicative of an underlying issue + + + A critical error has occurred. Generally this will + be followed by the network layer shutting down, although the + stability of the library after an error is uncertain + + + Used for internal testing, this logging level can + generate very noisy (long and/or repetitive) messages. Don't + pass this to the Log() function, use DebugLog() instead. + + + + + The InternalDictionary class is used through the library for storing key/value pairs. + It is intended to be a replacement for the generic Dictionary class and should + be used in its place. It contains several methods for allowing access to the data from + outside the library that are read only and thread safe. + + + Key + Value + + + Internal dictionary that this class wraps around. Do not + modify or enumerate the contents of this dictionary without locking + on this member + + + + Initializes a new instance of the Class + with the specified key/value, has the default initial capacity. + + + + // initialize a new InternalDictionary named testDict with a string as the key and an int as the value. + public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(); + + + + + + Initializes a new instance of the Class + with the specified key/value, has its initial valies copied from the specified + + + + to copy initial values from + + + // initialize a new InternalDictionary named testAvName with a UUID as the key and an string as the value. + // populates with copied values from example KeyNameCache Dictionary. + + // create source dictionary + Dictionary<UUID, string> KeyNameCache = new Dictionary<UUID, string>(); + KeyNameCache.Add("8300f94a-7970-7810-cf2c-fc9aa6cdda24", "Jack Avatar"); + KeyNameCache.Add("27ba1e40-13f7-0708-3e98-5819d780bd62", "Jill Avatar"); + + // Initialize new dictionary. + public InternalDictionary<UUID, string> testAvName = new InternalDictionary<UUID, string>(KeyNameCache); + + + + + + Initializes a new instance of the Class + with the specified key/value, With its initial capacity specified. + + Initial size of dictionary + + + // initialize a new InternalDictionary named testDict with a string as the key and an int as the value, + // initially allocated room for 10 entries. + public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(10); + + + + + + Try to get entry from with specified key + + Key to use for lookup + Value returned + if specified key exists, if not found + + + // find your avatar using the Simulator.ObjectsAvatars InternalDictionary: + Avatar av; + if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) + Console.WriteLine("Found Avatar {0}", av.Name); + + + + + + + Finds the specified match. + + The match. + Matched value + + + // use a delegate to find a prim in the ObjectsPrimitives InternalDictionary + // with the ID 95683496 + uint findID = 95683496; + Primitive findPrim = sim.ObjectsPrimitives.Find( + delegate(Primitive prim) { return prim.ID == findID; }); + + + + + Find All items in an + return matching items. + a containing found items. + + Find All prims within 20 meters and store them in a List + + int radius = 20; + List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( + delegate(Primitive prim) { + Vector3 pos = prim.Position; + return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); + } + ); + + + + + Find All items in an + return matching keys. + a containing found keys. + + Find All keys which also exist in another dictionary + + List<UUID> matches = myDict.FindAll( + delegate(UUID id) { + return myOtherDict.ContainsKey(id); + } + ); + + + + + Perform an on each entry in an + to perform + + + // Iterates over the ObjectsPrimitives InternalDictionary and prints out some information. + Client.Network.CurrentSim.ObjectsPrimitives.ForEach( + delegate(Primitive prim) + { + if (prim.Text != null) + { + Console.WriteLine("NAME={0} ID = {1} TEXT = '{2}'", + prim.PropertiesFamily.Name, prim.ID, prim.Text); + } + }); + + + + + Perform an on each key of an + to perform + + + + Perform an on each KeyValuePair of an + + to perform + + + Check if Key exists in Dictionary + Key to check for + if found, otherwise + + + Check if Value exists in Dictionary + Value to check for + if found, otherwise + + + + Adds the specified key to the dictionary, dictionary locking is not performed, + + + The key + The value + + + + Removes the specified key, dictionary locking is not performed + + The key. + if successful, otherwise + + + + Gets the number of Key/Value pairs contained in the + + + + + Indexer for the dictionary + + The key + The value + + + + Exception class to identify inventory exceptions + + + + + Responsible for maintaining inventory structure. Inventory constructs nodes + and manages node children as is necessary to maintain a coherant hirarchy. + Other classes should not manipulate or create InventoryNodes explicitly. When + A node's parent changes (when a folder is moved, for example) simply pass + Inventory the updated InventoryFolder and it will make the appropriate changes + to its internal representation. + + + + The event subscribers, null of no subscribers + + + Raises the InventoryObjectUpdated Event + A InventoryObjectUpdatedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the InventoryObjectRemoved Event + A InventoryObjectRemovedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the InventoryObjectAdded Event + A InventoryObjectAddedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + + Returns the contents of the specified folder + + A folder's UUID + The contents of the folder corresponding to folder + When folder does not exist in the inventory + + + + Updates the state of the InventoryNode and inventory data structure that + is responsible for the InventoryObject. If the item was previously not added to inventory, + it adds the item, and updates structure accordingly. If it was, it updates the + InventoryNode, changing the parent node if item.parentUUID does + not match node.Parent.Data.UUID. + + You can not set the inventory root folder using this method + + The InventoryObject to store + + + + Removes the InventoryObject and all related node data from Inventory. + + The InventoryObject to remove. + + + + Used to find out if Inventory contains the InventoryObject + specified by uuid. + + The UUID to check. + true if inventory contains uuid, false otherwise + + + + Saves the current inventory structure to a cache file + + Name of the cache file to save to + + + + Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful. + + Name of the cache file to load + The number of inventory items sucessfully reconstructed into the inventory node tree + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + + The root folder of this avatars inventory + + + + + The default shared library folder + + + + + The root node of the avatars inventory + + + + + The root node of the default shared library + + + + + By using the bracket operator on this class, the program can get the + InventoryObject designated by the specified uuid. If the value for the corresponding + UUID is null, the call is equivelant to a call to RemoveNodeFor(this[uuid]). + If the value is non-null, it is equivelant to a call to UpdateNodeFor(value), + the uuid parameter is ignored. + + The UUID of the InventoryObject to get or set, ignored if set to non-null value. + The InventoryObject corresponding to uuid. + + + Sort by name + + + Sort by date + + + Sort folders by name, regardless of whether items are + sorted by name or date + + + Place system folders at the top + + + + Possible destinations for DeRezObject request + + + + + + + Copy from in-world to agent inventory + + + Derez to TaskInventory + + + + + + Take Object + + + + + + Delete Object + + + Put an avatar attachment into agent inventory + + + + + + Return an object back to the owner's inventory + + + Return a deeded object back to the last owner's inventory + + + + Upper half of the Flags field for inventory items + + + + Indicates that the NextOwner permission will be set to the + most restrictive set of permissions found in the object set + (including linkset items and object inventory items) on next rez + + + Indicates that the object sale information has been + changed + + + If set, and a slam bit is set, indicates BaseMask will be overwritten on Rez + + + If set, and a slam bit is set, indicates OwnerMask will be overwritten on Rez + + + If set, and a slam bit is set, indicates GroupMask will be overwritten on Rez + + + If set, and a slam bit is set, indicates EveryoneMask will be overwritten on Rez + + + If set, and a slam bit is set, indicates NextOwnerMask will be overwritten on Rez + + + Indicates whether this object is composed of multiple + items or not + + + Indicates that the asset is only referenced by this + inventory item. If this item is deleted or updated to reference a + new assetID, the asset can be deleted + + + + Base Class for Inventory Items + + + + of item/folder + + + of parent folder + + + Name of item/folder + + + Item/Folder Owners + + + + Constructor, takes an itemID as a parameter + + The of the item + + + + + + + + + + + + + + + + Generates a number corresponding to the value of the object to support the use of a hash table, + suitable for use in hashing algorithms and data structures such as a hash table + + A Hashcode of all the combined InventoryBase fields + + + + Determine whether the specified object is equal to the current object + + InventoryBase object to compare against + true if objects are the same + + + + Determine whether the specified object is equal to the current object + + InventoryBase object to compare against + true if objects are the same + + + + Convert inventory to OSD + + OSD representation + + + + An Item in Inventory + + + + The of this item + + + The combined of this item + + + The type of item from + + + The type of item from the enum + + + The of the creator of this item + + + A Description of this item + + + The s this item is set to or owned by + + + If true, item is owned by a group + + + The price this item can be purchased for + + + The type of sale from the enum + + + Combined flags from + + + Time and date this inventory item was created, stored as + UTC (Coordinated Universal Time) + + + Used to update the AssetID in requests sent to the server + + + The of the previous owner of the item + + + + Construct a new InventoryItem object + + The of the item + + + + Construct a new InventoryItem object of a specific Type + + The type of item from + of the item + + + + Indicates inventory item is a link + + True if inventory item is a link to another inventory item + + + + + + + + + + + + + + + + Generates a number corresponding to the value of the object to support the use of a hash table. + Suitable for use in hashing algorithms and data structures such as a hash table + + A Hashcode of all the combined InventoryItem fields + + + + Compares an object + + The object to compare + true if comparison object matches + + + + Determine whether the specified object is equal to the current object + + The object to compare against + true if objects are the same + + + + Determine whether the specified object is equal to the current object + + The object to compare against + true if objects are the same + + + + Create InventoryItem from OSD + + OSD Data that makes up InventoryItem + Inventory item created + + + + Convert InventoryItem to OSD + + OSD representation of InventoryItem + + + + InventoryTexture Class representing a graphical image + + + + + + Construct an InventoryTexture object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryTexture object from a serialization stream + + + + + InventorySound Class representing a playable sound + + + + + Construct an InventorySound object + + A which becomes the + objects AssetUUID + + + + Construct an InventorySound object from a serialization stream + + + + + InventoryCallingCard Class, contains information on another avatar + + + + + Construct an InventoryCallingCard object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryCallingCard object from a serialization stream + + + + + InventoryLandmark Class, contains details on a specific location + + + + + Construct an InventoryLandmark object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryLandmark object from a serialization stream + + + + + Landmarks use the InventoryItemFlags struct and will have a flag of 1 set if they have been visited + + + + + InventoryObject Class contains details on a primitive or coalesced set of primitives + + + + + Construct an InventoryObject object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryObject object from a serialization stream + + + + + Gets or sets the upper byte of the Flags value + + + + + Gets or sets the object attachment point, the lower byte of the Flags value + + + + + InventoryNotecard Class, contains details on an encoded text document + + + + + Construct an InventoryNotecard object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryNotecard object from a serialization stream + + + + + InventoryCategory Class + + TODO: Is this even used for anything? + + + + Construct an InventoryCategory object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryCategory object from a serialization stream + + + + + InventoryLSL Class, represents a Linden Scripting Language object + + + + + Construct an InventoryLSL object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryLSL object from a serialization stream + + + + + InventorySnapshot Class, an image taken with the viewer + + + + + Construct an InventorySnapshot object + + A which becomes the + objects AssetUUID + + + + Construct an InventorySnapshot object from a serialization stream + + + + + InventoryAttachment Class, contains details on an attachable object + + + + + Construct an InventoryAttachment object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryAttachment object from a serialization stream + + + + + Get the last AttachmentPoint this object was attached to + + + + + InventoryWearable Class, details on a clothing item or body part + + + + + Construct an InventoryWearable object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryWearable object from a serialization stream + + + + + The , Skin, Shape, Skirt, Etc + + + + + InventoryAnimation Class, A bvh encoded object which animates an avatar + + + + + Construct an InventoryAnimation object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryAnimation object from a serialization stream + + + + + InventoryGesture Class, details on a series of animations, sounds, and actions + + + + + Construct an InventoryGesture object + + A which becomes the + objects AssetUUID + + + + Construct an InventoryGesture object from a serialization stream + + + + + A folder contains s and has certain attributes specific + to itself + + + + The Preferred for a folder. + + + The Version of this folder + + + Number of child items this folder contains. + + + + Constructor + + UUID of the folder + + + + + + + + + + Get Serilization data for this InventoryFolder object + + + + + Construct an InventoryFolder object from a serialization stream + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create InventoryFolder from OSD + + OSD Data that makes up InventoryFolder + Inventory folder created + + + + Convert InventoryItem to OSD + + OSD representation of InventoryItem + + + + Tools for dealing with agents inventory + + + + Used for converting shadow_id to asset_id + + + The event subscribers, null of no subscribers + + + Raises the ItemReceived Event + A ItemReceivedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the FolderUpdated Event + A FolderUpdatedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the InventoryObjectOffered Event + A InventoryObjectOfferedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the TaskItemReceived Event + A TaskItemReceivedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the FindObjectByPath Event + A FindObjectByPathEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the TaskInventoryReply Event + A TaskInventoryReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the SaveAssetToInventory Event + A SaveAssetToInventoryEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the ScriptRunningReply Event + A ScriptRunningReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + Partial mapping of AssetTypes to folder names + + + + Default constructor + + Reference to the GridClient object + + + + Fetch an inventory item from the dataserver + + The items + The item Owners + a integer representing the number of milliseconds to wait for results + An object on success, or null if no item was found + Items will also be sent to the event + + + + Request A single inventory item + + The items + The item Owners + + + + + Request inventory items + + Inventory items to request + Owners of the inventory items + + + + + Request inventory items via Capabilities + + Inventory items to request + Owners of the inventory items + + + + + Get contents of a folder + + The of the folder to search + The of the folders owner + true to retrieve folders + true to retrieve items + sort order to return results in + a integer representing the number of milliseconds to wait for results + A list of inventory items matching search criteria within folder + + InventoryFolder.DescendentCount will only be accurate if both folders and items are + requested + + + + Request the contents of an inventory folder + + The folder to search + The folder owners + true to return s contained in folder + true to return s containd in folder + the sort order to return items in + + + + + Request the contents of an inventory folder using HTTP capabilities + + The folder to search + The folder owners + true to return s contained in folder + true to return s containd in folder + the sort order to return items in + + + + + Returns the UUID of the folder (category) that defaults to + containing 'type'. The folder is not necessarily only for that + type + + This will return the root folder if one does not exist + + The UUID of the desired folder if found, the UUID of the RootFolder + if not found, or UUID.Zero on failure + + + + Find an object in inventory using a specific path to search + + The folder to begin the search in + The object owners + A string path to search + milliseconds to wait for a reply + Found items or if + timeout occurs or item is not found + + + + Find inventory items by path + + The folder to begin the search in + The object owners + A string path to search, folders/objects separated by a '/' + Results are sent to the event + + + + Search inventory Store object for an item or folder + + The folder to begin the search in + An array which creates a path to search + Number of levels below baseFolder to conduct searches + if True, will stop searching after first match is found + A list of inventory items found + + + + Move an inventory item or folder to a new location + + The item or folder to move + The to move item or folder to + + + + Move an inventory item or folder to a new location and change its name + + The item or folder to move + The to move item or folder to + The name to change the item or folder to + + + + Move and rename a folder + + The source folders + The destination folders + The name to change the folder to + + + + Update folder properties + + of the folder to update + Sets folder's parent to + Folder name + Folder type + + + + Move a folder + + The source folders + The destination folders + + + + Move multiple folders, the keys in the Dictionary parameter, + to a new parents, the value of that folder's key. + + A Dictionary containing the + of the source as the key, and the + of the destination as the value + + + + Move an inventory item to a new folder + + The of the source item to move + The of the destination folder + + + + Move and rename an inventory item + + The of the source item to move + The of the destination folder + The name to change the folder to + + + + Move multiple inventory items to new locations + + A Dictionary containing the + of the source item as the key, and the + of the destination folder as the value + + + + Remove descendants of a folder + + The of the folder + + + + Remove a single item from inventory + + The of the inventory item to remove + + + + Remove a folder from inventory + + The of the folder to remove + + + + Remove multiple items or folders from inventory + + A List containing the s of items to remove + A List containing the s of the folders to remove + + + + Empty the Lost and Found folder + + + + + Empty the Trash folder + + + + + + + + + + + Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. + + + + + + + + + + + + + Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. + + + + + + + + Creates a new inventory folder + + ID of the folder to put this folder in + Name of the folder to create + The UUID of the newly created folder + + + + Creates a new inventory folder + + ID of the folder to put this folder in + Name of the folder to create + Sets this folder as the default folder + for new assets of the specified type. Use AssetType.Unknown + to create a normal folder, otherwise it will likely create a + duplicate of an existing folder type + The UUID of the newly created folder + If you specify a preferred type of AsseType.Folder + it will create a new root folder which may likely cause all sorts + of strange problems + + + + Create an inventory item and upload asset data + + Asset data + Inventory item name + Inventory item description + Asset type + Inventory type + Put newly created inventory in this folder + Delegate that will receive feedback on success or failure + + + + Create an inventory item and upload asset data + + Asset data + Inventory item name + Inventory item description + Asset type + Inventory type + Put newly created inventory in this folder + Permission of the newly created item + (EveryoneMask, GroupMask, and NextOwnerMask of Permissions struct are supported) + Delegate that will receive feedback on success or failure + + + + Creates inventory link to another inventory item or folder + + Put newly created link in folder with this UUID + Inventory item or folder + Method to call upon creation of the link + + + + Creates inventory link to another inventory item + + Put newly created link in folder with this UUID + Original inventory item + Method to call upon creation of the link + + + + Creates inventory link to another inventory folder + + Put newly created link in folder with this UUID + Original inventory folder + Method to call upon creation of the link + + + + Creates inventory link to another inventory item or folder + + Put newly created link in folder with this UUID + Original item's UUID + Name + Description + Asset Type + Inventory Type + Transaction UUID + Method to call upon creation of the link + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Request a copy of an asset embedded within a notecard + + Usually UUID.Zero for copying an asset from a notecard + UUID of the notecard to request an asset from + Target folder for asset to go to in your inventory + UUID of the embedded asset + callback to run when item is copied to inventory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Save changes to notecard embedded in object contents + + Encoded notecard asset data + Notecard UUID + Object's UUID + Called upon finish of the upload with status information + + + + Upload new gesture asset for an inventory gesture item + + Encoded gesture asset + Gesture inventory UUID + Callback whick will be called when upload is complete + + + + Update an existing script in an agents Inventory + + A byte[] array containing the encoded scripts contents + the itemID of the script + if true, sets the script content to run on the mono interpreter + + + + + Update an existing script in an task Inventory + + A byte[] array containing the encoded scripts contents + the itemID of the script + UUID of the prim containting the script + if true, sets the script content to run on the mono interpreter + if true, sets the script to running + + + + + Rez an object from inventory + + Simulator to place object in + Rotation of the object when rezzed + Vector of where to place object + InventoryItem object containing item details + + + + Rez an object from inventory + + Simulator to place object in + Rotation of the object when rezzed + Vector of where to place object + InventoryItem object containing item details + UUID of group to own the object + + + + Rez an object from inventory + + Simulator to place object in + Rotation of the object when rezzed + Vector of where to place object + InventoryItem object containing item details + UUID of group to own the object + User defined queryID to correlate replies + If set to true, the CreateSelected flag + will be set on the rezzed object + + + + Rez an object from inventory + + Simulator to place object in + TaskID object when rezzed + Rotation of the object when rezzed + Vector of where to place object + InventoryItem object containing item details + UUID of group to own the object + User defined queryID to correlate replies + If set to true, the CreateSelected flag + will be set on the rezzed object + + + + DeRez an object from the simulator to the agents Objects folder in the agents Inventory + + The simulator Local ID of the object + If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed + + + + DeRez an object from the simulator and return to inventory + + The simulator Local ID of the object + The type of destination from the enum + The destination inventory folders -or- + if DeRezzing object to a tasks Inventory, the Tasks + The transaction ID for this request which + can be used to correlate this request with other packets + If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed + + + + Rez an item from inventory to its previous simulator location + + + + + + + + + Give an inventory item to another avatar + + The of the item to give + The name of the item + The type of the item from the enum + The of the recipient + true to generate a beameffect during transfer + + + + Give an inventory Folder with contents to another avatar + + The of the Folder to give + The name of the folder + The type of the item from the enum + The of the recipient + true to generate a beameffect during transfer + + + + Copy or move an from agent inventory to a task (primitive) inventory + + The target object + The item to copy or move from inventory + + For items with copy permissions a copy of the item is placed in the tasks inventory, + for no-copy items the object is moved to the tasks inventory + + + + Retrieve a listing of the items contained in a task (Primitive) + + The tasks + The tasks simulator local ID + milliseconds to wait for reply from simulator + A list containing the inventory items inside the task or null + if a timeout occurs + This request blocks until the response from the simulator arrives + or timeoutMS is exceeded + + + + Request the contents of a tasks (primitives) inventory from the + current simulator + + The LocalID of the object + + + + + Request the contents of a tasks (primitives) inventory + + The simulator Local ID of the object + A reference to the simulator object that contains the object + + + + + Move an item from a tasks (Primitive) inventory to the specified folder in the avatars inventory + + LocalID of the object in the simulator + UUID of the task item to move + The ID of the destination folder in this agents inventory + Simulator Object + Raises the event + + + + Remove an item from an objects (Prim) Inventory + + LocalID of the object in the simulator + UUID of the task item to remove + Simulator Object + You can confirm the removal by comparing the tasks inventory serial before and after the + request with the request combined with + the event + + + + Copy an InventoryScript item from the Agents Inventory into a primitives task inventory + + An unsigned integer representing a primitive being simulated + An which represents a script object from the agents inventory + true to set the scripts running state to enabled + A Unique Transaction ID + + The following example shows the basic steps necessary to copy a script from the agents inventory into a tasks inventory + and assumes the script exists in the agents inventory. + + uint primID = 95899503; // Fake prim ID + UUID scriptID = UUID.Parse("92a7fe8a-e949-dd39-a8d8-1681d8673232"); // Fake Script UUID in Inventory + + Client.Inventory.FolderContents(Client.Inventory.FindFolderForType(AssetType.LSLText), Client.Self.AgentID, + false, true, InventorySortOrder.ByName, 10000); + + Client.Inventory.RezScript(primID, (InventoryItem)Client.Inventory.Store[scriptID]); + + + + + + Request the running status of a script contained in a task (primitive) inventory + + The ID of the primitive containing the script + The ID of the script + The event can be used to obtain the results of the + request + + + + + Send a request to set the running state of a script contained in a task (primitive) inventory + + The ID of the primitive containing the script + The ID of the script + true to set the script running, false to stop a running script + To verify the change you can use the method combined + with the event + + + + Create a CRC from an InventoryItem + + The source InventoryItem + A uint representing the source InventoryItem as a CRC + + + + Reverses a cheesy XORing with a fixed UUID to convert a shadow_id to an asset_id + + Obfuscated shadow_id value + Deobfuscated asset_id value + + + + Does a cheesy XORing with a fixed UUID to convert an asset_id to a shadow_id + + asset_id value to obfuscate + Obfuscated shadow_id value + + + + Wrapper for creating a new object + + The type of item from the enum + The of the newly created object + An object with the type and id passed + + + + Parse the results of a RequestTaskInventory() response + + A string which contains the data from the task reply + A List containing the items contained within the tasks inventory + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + + UpdateCreateInventoryItem packets are received when a new inventory item + is created. This may occur when an object that's rezzed in world is + taken into inventory, when an item is created using the CreateInventoryItem + packet, or when an object is purchased + + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + an inventory object sent by another avatar or primitive + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + + Get this agents Inventory data + + + + + Callback for inventory item creation finishing + + Whether the request to create an inventory + item succeeded or not + Inventory item being created. If success is + false this will be null + + + + Callback for an inventory item being create from an uploaded asset + + true if inventory item creation was successful + + + + + + + + + + + + + Reply received when uploading an inventory asset + + Has upload been successful + Error message if upload failed + Inventory asset UUID + New asset UUID + + + + Delegate that is invoked when script upload is completed + + Has upload succeded (note, there still might be compile errors) + Upload status message + Is compilation successful + If compilation failed, list of error messages, null on compilation success + Script inventory UUID + Script's new asset UUID + + + Set to true to accept offer, false to decline it + + + The folder to accept the inventory into, if null default folder for will be used + + + + Callback when an inventory object is accepted and received from a + task inventory. This is the callback in which you actually get + the ItemID, as in ObjectOfferedCallback it is null when received + from a task. + + + + + + + + + + + + + + + + De-serialization constructor for the InventoryNode Class + + + + + Serialization handler for the InventoryNode Class + + + + + De-serialization handler for the InventoryNode Class + + + + + + + + + + + + + User data + + + + + + + + + + + + + For inventory folder nodes specifies weather the folder needs to be + refreshed from the server + + + + + Singleton logging class for the entire library + + + + log4net logging engine + + + + Default constructor + + + + + Send a log message to the logging engine + + The log message + The severity of the log entry + + + + Send a log message to the logging engine + + The log message + The severity of the log entry + Instance of the client + + + + Send a log message to the logging engine + + The log message + The severity of the log entry + Exception that was raised + + + + Send a log message to the logging engine + + The log message + The severity of the log entry + Instance of the client + Exception that was raised + + + + If the library is compiled with DEBUG defined, an event will be + fired if an OnLogMessage handler is registered and the + message will be sent to the logging engine + + The message to log at the DEBUG level to the + current logging engine + + + + If the library is compiled with DEBUG defined and + GridClient.Settings.DEBUG is true, an event will be + fired if an OnLogMessage handler is registered and the + message will be sent to the logging engine + + The message to log at the DEBUG level to the + current logging engine + Instance of the client + + + Triggered whenever a message is logged. If this is left + null, log messages will go to the console + + + + Callback used for client apps to receive log messages from + the library + + Data being logged + The severity of the log entry from + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Status of the last application run. + Used for error reporting to the grid login service for statistical purposes. + + + + Application exited normally + + + Application froze + + + Application detected error and exited abnormally + + + Other crash + + + Application froze during logout + + + Application crashed during logout + + + + Login Request Parameters + + + + The URL of the Login Server + + + The number of milliseconds to wait before a login is considered + failed due to timeout + + + The request method + login_to_simulator is currently the only supported method + + + The Agents First name + + + The Agents Last name + + + A md5 hashed password + plaintext password will be automatically hashed + + + The agents starting location once logged in + Either "last", "home", or a string encoded URI + containing the simulator name and x/y/z coordinates e.g: uri:hooper&128&152&17 + + + A string containing the client software channel information + Second Life Release + + + The client software version information + The official viewer uses: Second Life Release n.n.n.n + where n is replaced with the current version of the viewer + + + A string containing the platform information the agent is running on + + + A string hash of the network cards Mac Address + + + Unknown or deprecated + + + A string hash of the first disk drives ID used to identify this clients uniqueness + + + A string containing the viewers Software, this is not directly sent to the login server but + instead is used to generate the Version string + + + A string representing the software creator. This is not directly sent to the login server but + is used by the library to generate the Version information + + + If true, this agent agrees to the Terms of Service of the grid its connecting to + + + Unknown + + + Status of the last application run sent to the grid login server for statistical purposes + + + An array of string sent to the login server to enable various options + + + A randomly generated ID to distinguish between login attempts. This value is only used + internally in the library and is never sent over the wire + + + + Default constuctor, initializes sane default values + + + + + Instantiates new LoginParams object and fills in the values + + Instance of GridClient to read settings from + Login first name + Login last name + Password + Login channnel (application name) + Client version, should be application name + version number + + + + Instantiates new LoginParams object and fills in the values + + Instance of GridClient to read settings from + Login first name + Login last name + Password + Login channnel (application name) + Client version, should be application name + version number + URI of the login server + + + + The decoded data returned from the login server after a successful login + + + + true, false, indeterminate + + + Login message of the day + + + M or PG, also agent_region_access and agent_access_max + + + + Parse LLSD Login Reply Data + + An + contaning the login response data + XML-RPC logins do not require this as XML-RPC.NET + automatically populates the struct properly using attributes + + + + Login Routines + + + NetworkManager is responsible for managing the network layer of + OpenMetaverse. It tracks all the server connections, serializes + outgoing traffic and deserializes incoming traffic, and provides + instances of delegates for network-related events. + + + + The event subscribers, null of no subscribers + + + Raises the LoginProgress Event + A LoginProgressEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + Seed CAPS URL returned from the login server + + + Maximum number of groups an agent can belong to, -1 for unlimited + + + Server side baking service URL + + + Parsed login response data + + + A list of packets obtained during the login process which + networkmanager will log but not process + + + + Generate sane default values for a login request + + Account first name + Account last name + Account password + Client application name (channel) + Client application name + version + A populated struct containing + sane defaults + + + + Simplified login that takes the most common and required fields + + Account first name + Account last name + Account password + Client application name (channel) + Client application name + version + Whether the login was successful or not. On failure the + LoginErrorKey string will contain the error code and LoginMessage + will contain a description of the error + + + + Simplified login that takes the most common fields along with a + starting location URI, and can accept an MD5 string instead of a + plaintext password + + Account first name + Account last name + Account password or MD5 hash of the password + such as $1$1682a1e45e9f957dcdf0bb56eb43319c + Client application name (channel) + Starting location URI that can be built with + StartLocation() + Client application name + version + Whether the login was successful or not. On failure the + LoginErrorKey string will contain the error code and LoginMessage + will contain a description of the error + + + + Login that takes a struct of all the values that will be passed to + the login server + + The values that will be passed to the login + server, all fields must be set even if they are String.Empty + Whether the login was successful or not. On failure the + LoginErrorKey string will contain the error code and LoginMessage + will contain a description of the error + + + + Build a start location URI for passing to the Login function + + Name of the simulator to start in + X coordinate to start at + Y coordinate to start at + Z coordinate to start at + String with a URI that can be used to login to a specified + location + + + + LoginParams and the initial login XmlRpcRequest were made on a remote machine. + This method now initializes libomv with the results. + + + + + Handles response from XML-RPC login replies + + + + + Handles response from XML-RPC login replies with already parsed LoginResponseData + + + + + Handle response from LLSD login replies + + + + + + + + Get current OS + + Either "Win" or "Linux" + + + + Get clients default Mac Address + + A string containing the first found Mac Address + + + The event subscribers, null of no subscribers + + + Raises the PacketSent Event + A PacketSentEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the LoggedOut Event + A LoggedOutEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the SimConnecting Event + A SimConnectingEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the SimConnected Event + A SimConnectedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the SimDisconnected Event + A SimDisconnectedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the Disconnected Event + A DisconnectedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the SimChanged Event + A SimChangedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the EventQueueRunning Event + A EventQueueRunningEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + All of the simulators we are currently connected to + + + Handlers for incoming capability events + + + Handlers for incoming packets + + + Incoming packets that are awaiting handling + + + Outgoing packets that are awaiting handling + + + + Default constructor + + Reference to the GridClient object + + + + Register an event handler for a packet. This is a low level event + interface and should only be used if you are doing something not + supported in the library + + Packet type to trigger events for + Callback to fire when a packet of this type + is received + + + + Register an event handler for a packet. This is a low level event + interface and should only be used if you are doing something not + supported in the library + + Packet type to trigger events for + Callback to fire when a packet of this type + is received + True if the callback should be ran + asynchronously. Only set this to false (synchronous for callbacks + that will always complete quickly) + If any callback for a packet type is marked as + asynchronous, all callbacks for that packet type will be fired + asynchronously + + + + Unregister an event handler for a packet. This is a low level event + interface and should only be used if you are doing something not + supported in the library + + Packet type this callback is registered with + Callback to stop firing events for + + + + Register a CAPS event handler. This is a low level event interface + and should only be used if you are doing something not supported in + the library + + Name of the CAPS event to register a handler for + Callback to fire when a CAPS event is received + + + + Unregister a CAPS event handler. This is a low level event interface + and should only be used if you are doing something not supported in + the library + + Name of the CAPS event this callback is + registered with + Callback to stop firing events for + + + + Send a packet to the simulator the avatar is currently occupying + + Packet to send + + + + Send a packet to a specified simulator + + Packet to send + Simulator to send the packet to + + + + Connect to a simulator + + IP address to connect to + Port to connect to + Handle for this simulator, to identify its + location in the grid + Whether to set CurrentSim to this new + connection, use this if the avatar is moving in to this simulator + URL of the capabilities server to use for + this sim connection + A Simulator object on success, otherwise null + + + + Connect to a simulator + + IP address and port to connect to + Handle for this simulator, to identify its + location in the grid + Whether to set CurrentSim to this new + connection, use this if the avatar is moving in to this simulator + URL of the capabilities server to use for + this sim connection + A Simulator object on success, otherwise null + + + + Initiate a blocking logout request. This will return when the logout + handshake has completed or when Settings.LOGOUT_TIMEOUT + has expired and the network layer is manually shut down + + + + + Initiate the logout process. Check if logout succeeded with the + OnLogoutReply event, and if this does not fire the + Shutdown() function needs to be manually called + + + + + Close a connection to the given simulator + + + + + + + Shutdown will disconnect all the sims except for the current sim + first, and then kill the connection to CurrentSim. This should only + be called if the logout process times out on RequestLogout + + Type of shutdown + + + + Shutdown will disconnect all the sims except for the current sim + first, and then kill the connection to CurrentSim. This should only + be called if the logout process times out on RequestLogout + + Type of shutdown + Shutdown message + + + + Searches through the list of currently connected simulators to find + one attached to the given IPEndPoint + + IPEndPoint of the Simulator to search for + A Simulator reference on success, otherwise null + + + + Fire an event when an event queue connects for capabilities + + Simulator the event queue is attached to + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Raised when the simulator sends us data containing + ... + + + Called when a reply is received from the login server, the + login sequence will block until this event returns + + + Current state of logging in + + + Upon login failure, contains a short string key for the + type of login error that occurred + + + The raw XML-RPC reply from the login server, exactly as it + was received (minus the HTTP header) + + + During login this contains a descriptive version of + LoginStatusCode. After a successful login this will contain the + message of the day, and after a failed login a descriptive error + message will be returned + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Unique identifier associated with our connections to + simulators + + + The simulator that the logged in avatar is currently + occupying + + + Shows whether the network layer is logged in to the + grid or not + + + Number of packets in the incoming queue + + + Number of packets in the outgoing queue + + + + + + + + + + + + + + Explains why a simulator or the grid disconnected from us + + + + The client requested the logout or simulator disconnect + + + The server notified us that it is disconnecting + + + Either a socket was closed or network traffic timed out + + + The last active simulator shut down + + + + Holds a simulator reference and a decoded packet, these structs are put in + the packet inbox for event handling + + + + Reference to the simulator that this packet came from + + + Packet that needs to be processed + + + + Holds a simulator reference and a serialized packet, these structs are put in + the packet outbox for sending + + + + Reference to the simulator this packet is destined for + + + Packet that needs to be sent + + + Sequence number of the wrapped packet + + + Number of times this packet has been resent + + + Environment.TickCount when this packet was last sent over the wire + + + Type of the packet + + + + A Name Value pair with additional settings, used in the protocol + primarily to transmit avatar names and active group in object packets + + + + + + + + + + + + + + + + + + + + Constructor that takes all the fields as parameters + + + + + + + + + + Constructor that takes a single line from a NameValue field + + + + + Type of the value + + + Unknown + + + String value + + + + + + + + + + + + + + + Deprecated + + + String value, but designated as an asset + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No report + + + Unknown report type + + + Bug report + + + Complaint report + + + Customer service report + + + + Bitflag field for ObjectUpdateCompressed data blocks, describing + which options are present for each object + + + + Unknown + + + Whether the object has a TreeSpecies + + + Whether the object has floating text ala llSetText + + + Whether the object has an active particle system + + + Whether the object has sound attached to it + + + Whether the object is attached to a root object or not + + + Whether the object has texture animation settings + + + Whether the object has an angular velocity + + + Whether the object has a name value pairs string + + + Whether the object has a Media URL set + + + + Specific Flags for MultipleObjectUpdate requests + + + + None + + + Change position of prims + + + Change rotation of prims + + + Change size of prims + + + Perform operation on link set + + + Scale prims uniformly, same as selecing ctrl+shift in the + viewer. Used in conjunction with Scale + + + + Special values in PayPriceReply. If the price is not one of these + literal value of the price should be use + + + + + Indicates that this pay option should be hidden + + + + + Indicates that this pay option should have the default value + + + + + Contains the variables sent in an object update packet for objects. + Used to track position and movement of prims and avatars + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Handles all network traffic related to prims and avatar positions and + movement. + + + + The event subscribers, null of no subscribers + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the ObjectProperties Event + A ObjectPropertiesEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the ObjectPropertiesUpdated Event + A ObjectPropertiesUpdatedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the ObjectPropertiesFamily Event + A ObjectPropertiesFamilyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the AvatarUpdate Event + A AvatarUpdateEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the ObjectDataBlockUpdate Event + A ObjectDataBlockUpdateEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the KillObject Event + A KillObjectEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the KillObjects Event + A KillObjectsEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the AvatarSitChanged Event + A AvatarSitChangedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the PayPriceReply Event + A PayPriceReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the PhysicsProperties Event + A PhysicsPropertiesEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + Reference to the GridClient object + + + Does periodic dead reckoning calculation to convert + velocity and acceleration to new positions for objects + + + + Construct a new instance of the ObjectManager class + + A reference to the instance + + + + Request information for a single object from a + you are currently connected to + + The the object is located + The Local ID of the object + + + + Request information for multiple objects contained in + the same simulator + + The the objects are located + An array containing the Local IDs of the objects + + + + Attempt to purchase an original object, a copy, or the contents of + an object + + The the object is located + The Local ID of the object + Whether the original, a copy, or the object + contents are on sale. This is used for verification, if the this + sale type is not valid for the object the purchase will fail + Price of the object. This is used for + verification, if it does not match the actual price the purchase + will fail + Group ID that will be associated with the new + purchase + Inventory folder UUID where the object or objects + purchased should be placed + + + BuyObject(Client.Network.CurrentSim, 500, SaleType.Copy, + 100, UUID.Zero, Client.Self.InventoryRootFolderUUID); + + + + + + Request prices that should be displayed in pay dialog. This will triggger the simulator + to send us back a PayPriceReply which can be handled by OnPayPriceReply event + + The the object is located + The ID of the object + The result is raised in the event + + + + Select a single object. This will cause the to send us + an which will raise the event + + The the object is located + The Local ID of the object + + + + + Select a single object. This will cause the to send us + an which will raise the event + + The the object is located + The Local ID of the object + if true, a call to is + made immediately following the request + + + + + Select multiple objects. This will cause the to send us + an which will raise the event + + The the objects are located + An array containing the Local IDs of the objects + Should objects be deselected immediately after selection + - Select multiple objects. This will cause the to send us - an which will raise the event - - The the objects are located - An array containing the Local IDs of the objects - + Select multiple objects. This will cause the to send us + an which will raise the event + + The the objects are located + An array containing the Local IDs of the objects + + + + + Update the properties of an object + + The the object is located + The Local ID of the object + true to turn the objects physical property on + true to turn the objects temporary property on + true to turn the objects phantom property on + true to turn the objects cast shadows property on + + + + Update the properties of an object + + The the object is located + The Local ID of the object + true to turn the objects physical property on + true to turn the objects temporary property on + true to turn the objects phantom property on + true to turn the objects cast shadows property on + Type of the represetnation prim will have in the physics engine + Density - normal value 1000 + Friction - normal value 0.6 + Restitution - standard value 0.5 + Gravity multiplier - standar value 1.0 + + + + Sets the sale properties of a single object + + The the object is located + The Local ID of the object + One of the options from the enum + The price of the object + + + + Sets the sale properties of multiple objects + + The the objects are located + An array containing the Local IDs of the objects + One of the options from the enum + The price of the object + + + + Deselect a single object + + The the object is located + The Local ID of the object + + + + Deselect multiple objects. + + The the objects are located + An array containing the Local IDs of the objects + + + + Perform a click action on an object + + The the object is located + The Local ID of the object + + + + Perform a click action (Grab) on a single object + + The the object is located + The Local ID of the object + The texture coordinates to touch + The surface coordinates to touch + The face of the position to touch + The region coordinates of the position to touch + The surface normal of the position to touch (A normal is a vector perpindicular to the surface) + The surface binormal of the position to touch (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space + + + + Create (rez) a new prim object in a simulator + + A reference to the object to place the object in + Data describing the prim object to rez + Group ID that this prim will be set to, or UUID.Zero if you + do not want the object to be associated with a specific group + An approximation of the position at which to rez the prim + Scale vector to size this prim + Rotation quaternion to rotate this prim + Due to the way client prim rezzing is done on the server, + the requested position for an object is only close to where the prim + actually ends up. If you desire exact placement you'll need to + follow up by moving the object after it has been created. This + function will not set textures, light and flexible data, or other + extended primitive properties + + + + Create (rez) a new prim object in a simulator + + A reference to the object to place the object in + Data describing the prim object to rez + Group ID that this prim will be set to, or UUID.Zero if you + do not want the object to be associated with a specific group + An approximation of the position at which to rez the prim + Scale vector to size this prim + Rotation quaternion to rotate this prim + Specify the + Due to the way client prim rezzing is done on the server, + the requested position for an object is only close to where the prim + actually ends up. If you desire exact placement you'll need to + follow up by moving the object after it has been created. This + function will not set textures, light and flexible data, or other + extended primitive properties + + + + Rez a Linden tree + + A reference to the object where the object resides + The size of the tree + The rotation of the tree + The position of the tree + The Type of tree + The of the group to set the tree to, + or UUID.Zero if no group is to be set + true to use the "new" Linden trees, false to use the old + + + + Rez grass and ground cover + + A reference to the object where the object resides + The size of the grass + The rotation of the grass + The position of the grass + The type of grass from the enum + The of the group to set the tree to, + or UUID.Zero if no group is to be set + + + + Set the textures to apply to the faces of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The texture data to apply + + + + Set the textures to apply to the faces of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The texture data to apply + A media URL (not used) + + + + Set the Light data on an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A object containing the data to set + + + + Set the flexible data on an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A object containing the data to set + + + + Set the sculptie texture and data on an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A object containing the data to set + + + + Unset additional primitive parameters on an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The extra parameters to set + + + + Link multiple prims into a linkset + + A reference to the object where the objects reside + An array which contains the IDs of the objects to link + The last object in the array will be the root object of the linkset TODO: Is this true? + + + + Delink/Unlink multiple prims from a linkset + + A reference to the object where the objects reside + An array which contains the IDs of the objects to delink + + + + Change the rotation of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new rotation of the object + + + + Set the name of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A string containing the new name of the object + + + + Set the name of multiple objects + + A reference to the object where the objects reside + An array which contains the IDs of the objects to change the name of + An array which contains the new names of the objects + + + + Set the description of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A string containing the new description of the object + + + + Set the descriptions of multiple objects + + A reference to the object where the objects reside + An array which contains the IDs of the objects to change the description of + An array which contains the new descriptions of the objects + + + + Attach an object to this avatar + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The point on the avatar the object will be attached + The rotation of the attached object + + + + Drop an attached object from this avatar + + A reference to the + object where the objects reside. This will always be the simulator the avatar is currently in + + The object's ID which is local to the simulator the object is in + + + + Detach an object from yourself + + A reference to the + object where the objects reside + + This will always be the simulator the avatar is currently in + + An array which contains the IDs of the objects to detach + + + + Change the position of an object, Will change position of entire linkset + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new position of the object + + + + Change the position of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new position of the object + if true, will change position of (this) child prim only, not entire linkset + + + + Change the Scale (size) of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new scale of the object + If true, will change scale of this prim only, not entire linkset + True to resize prims uniformly + + + + Change the Rotation of an object that is either a child or a whole linkset + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new scale of the object + If true, will change rotation of this prim only, not entire linkset + + + + Send a Multiple Object Update packet to change the size, scale or rotation of a primitive + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new rotation, size, or position of the target object + The flags from the Enum + + + + Deed an object (prim) to a group, Object must be shared with group which + can be accomplished with SetPermissions() + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The of the group to deed the object to + + + + Deed multiple objects (prims) to a group, Objects must be shared with group which + can be accomplished with SetPermissions() + + A reference to the object where the object resides + An array which contains the IDs of the objects to deed + The of the group to deed the object to + + + + Set the permissions on multiple objects + + A reference to the object where the objects reside + An array which contains the IDs of the objects to set the permissions on + The new Who mask to set + Which permission to modify + The new state of permission + + + + Request additional properties for an object + + A reference to the object where the object resides + + + + + Request additional properties for an object + + A reference to the object where the object resides + Absolute UUID of the object + Whether to require server acknowledgement of this request + + + + Set the ownership of a list of objects to the specified group + + A reference to the object where the objects reside + An array which contains the IDs of the objects to set the group id on + The Groups ID + + + + Update current URL of the previously set prim media + + UUID of the prim + Set current URL to this + Prim face number + Simulator in which prim is located + + + + Set object media + + UUID of the prim + Array the length of prims number of faces. Null on face indexes where there is + no media, on faces which contain the media + Simulatior in which prim is located + + + + Retrieve information about object media + + UUID of the primitive + Simulator where prim is located + Call this callback when done + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + + A terse object update, used when a transformation matrix or + velocity/acceleration for an object changes but nothing else + (scale/position/rotation/acceleration/velocity) + + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + + + + + + + + + + Setup construction data for a basic primitive shape + + Primitive shape to construct + Construction data that can be plugged into a + + + + + + + + + + + + + + + + + + + + Set the Shape data of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + Data describing the prim shape + + + + Set the Material data of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new material of the object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Raised when the simulator sends us data containing + A , Foliage or Attachment + + + + + Raised when the simulator sends us data containing + additional information + + + + + Raised when the simulator sends us data containing + Primitive.ObjectProperties for an object we are currently tracking + + + Raised when the simulator sends us data containing + additional and details + + + + Raised when the simulator sends us data containing + updated information for an + + + Raised when the simulator sends us data containing + and movement changes + + + Raised when the simulator sends us data containing + updates to an Objects DataBlock + + + Raised when the simulator informs us an + or is no longer within view + + + Raised when the simulator informs us when a group of + or is no longer within view + + + Raised when the simulator sends us data containing + updated sit information for our + + + Raised when the simulator sends us data containing + purchase price information for a + + + Raised when the simulator sends us data containing + additional information + + + + + + Callback for getting object media data via CAP + + Indicates if the operation was succesfull + Object media version string + Array indexed on prim face of media entry data + + + Provides data for the event + The event occurs when the simulator sends + an containing a Primitive, Foliage or Attachment data + Note 1: The event will not be raised when the object is an Avatar + Note 2: It is possible for the to be + raised twice for the same object if for example the primitive moved to a new simulator, then returned to the current simulator or + if an Avatar crosses the border into a new simulator and returns to the current simulator + + + The following code example uses the , , and + properties to display new Primitives and Attachments on the window. + + // Subscribe to the event that gives us prim and foliage information + Client.Objects.ObjectUpdate += Objects_ObjectUpdate; + + + private void Objects_ObjectUpdate(object sender, PrimEventArgs e) + { + Console.WriteLine("Primitive {0} {1} in {2} is an attachment {3}", e.Prim.ID, e.Prim.LocalID, e.Simulator.Name, e.IsAttachment); + } + + + + + + + + + Construct a new instance of the PrimEventArgs class + + The simulator the object originated from + The Primitive + The simulator time dilation + The prim was not in the dictionary before this update + true if the primitive represents an attachment to an agent + + + Get the simulator the originated from + + + Get the details + + + true if the did not exist in the dictionary before this update (always true if object tracking has been disabled) + + + true if the is attached to an + + + Get the simulator Time Dilation + + + Provides data for the event + The event occurs when the simulator sends + an containing Avatar data + Note 1: The event will not be raised when the object is an Avatar + Note 2: It is possible for the to be + raised twice for the same avatar if for example the avatar moved to a new simulator, then returned to the current simulator + + + The following code example uses the property to make a request for the top picks + using the method in the class to display the names + of our own agents picks listings on the window. + + // subscribe to the AvatarUpdate event to get our information + Client.Objects.AvatarUpdate += Objects_AvatarUpdate; + Client.Avatars.AvatarPicksReply += Avatars_AvatarPicksReply; + + private void Objects_AvatarUpdate(object sender, AvatarUpdateEventArgs e) + { + // we only want our own data + if (e.Avatar.LocalID == Client.Self.LocalID) + { + // Unsubscribe from the avatar update event to prevent a loop + // where we continually request the picks every time we get an update for ourselves + Client.Objects.AvatarUpdate -= Objects_AvatarUpdate; + // make the top picks request through AvatarManager + Client.Avatars.RequestAvatarPicks(e.Avatar.ID); + } + } + + private void Avatars_AvatarPicksReply(object sender, AvatarPicksReplyEventArgs e) + { + // we'll unsubscribe from the AvatarPicksReply event since we now have the data + // we were looking for + Client.Avatars.AvatarPicksReply -= Avatars_AvatarPicksReply; + // loop through the dictionary and extract the names of the top picks from our profile + foreach (var pickName in e.Picks.Values) + { + Console.WriteLine(pickName); + } + } + + + + + + + + Construct a new instance of the AvatarUpdateEventArgs class + + The simulator the packet originated from + The data + The simulator time dilation + The avatar was not in the dictionary before this update + + + Get the simulator the object originated from + + + Get the data + + + Get the simulator time dilation + + + true if the did not exist in the dictionary before this update (always true if avatar tracking has been disabled) + + + Provides additional primitive data for the event + The event occurs when the simulator sends + an containing additional details for a Primitive, Foliage data or Attachment data + The event is also raised when a request is + made. + + + The following code example uses the , and + + properties to display new attachments and send a request for additional properties containing the name of the + attachment then display it on the window. + + // Subscribe to the event that provides additional primitive details + Client.Objects.ObjectProperties += Objects_ObjectProperties; + + // handle the properties data that arrives + private void Objects_ObjectProperties(object sender, ObjectPropertiesEventArgs e) + { + Console.WriteLine("Primitive Properties: {0} Name is {1}", e.Properties.ObjectID, e.Properties.Name); + } + + + + + + Construct a new instance of the ObjectPropertiesEventArgs class + + The simulator the object is located + The primitive Properties + + + Get the simulator the object is located + + + Get the primitive properties + + + Provides additional primitive data for the event + The event occurs when the simulator sends + an containing additional details for a Primitive or Foliage data that is currently + being tracked in the dictionary + The event is also raised when a request is + made and is enabled + + + + + Construct a new instance of the ObjectPropertiesUpdatedEvenrArgs class + + The simulator the object is located + The Primitive + The primitive Properties + + + Get the primitive details + + + Provides additional primitive data, permissions and sale info for the event + The event occurs when the simulator sends + an containing additional details for a Primitive, Foliage data or Attachment. This includes + Permissions, Sale info, and other basic details on an object + The event is also raised when a request is + made, the viewer equivalent is hovering the mouse cursor over an object + + + + Get the simulator the object is located + + + + + + + + + Provides primitive data containing updated location, velocity, rotation, textures for the event + The event occurs when the simulator sends updated location, velocity, rotation, etc + + + + Get the simulator the object is located + + + Get the primitive details + + + + + + + + + + + + + + Get the simulator the object is located + + + Get the primitive details + + + + + + + + + + + + + + + Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the + event + + + Get the simulator the object is located + + + The LocalID of the object + + + Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the + event + + + Get the simulator the object is located + + + The LocalID of the object + + + + Provides updates sit position data + + + + Get the simulator the object is located + + + + + + + + + + + + + + + + + Get the simulator the object is located + + + + + + + + + + + + + Indicates if the operation was successful + + + + + Media version string + + + + + Array of media entries indexed by face number + + + + + Set when simulator sends us infomation on primitive's physical properties + + + + Simulator where the message originated + + + Updated physical properties + + + + Constructor + + Simulator where the message originated + Updated physical properties + + + Size of the byte array used to store raw packet data + + + Raw packet data buffer + + + Length of the data to transmit + + + EndPoint of the remote host + + + + Create an allocated UDP packet buffer for receiving a packet + + + + + Create an allocated UDP packet buffer for sending a packet + + EndPoint of the remote host + + + + Create an allocated UDP packet buffer for sending a packet + + EndPoint of the remote host + Size of the buffer to allocate for packet data + + + + Object pool for packet buffers. This is used to allocate memory for all + incoming and outgoing packets, and zerocoding buffers for those packets + + + + + Creates a new instance of the ObjectPoolBase class. Initialize MUST be called + after using this constructor. + + + + + Creates a new instance of the ObjectPool Base class. + + The object pool is composed of segments, which + are allocated whenever the size of the pool is exceeded. The number of items + in a segment should be large enough that allocating a new segmeng is a rare + thing. For example, on a server that will have 10k people logged in at once, + the receive buffer object pool should have segment sizes of at least 1000 + byte arrays per segment. + + The minimun number of segments that may exist. + Perform a full GC.Collect whenever a segment is allocated, and then again after allocation to compact the heap. + The frequency which segments are checked to see if they're eligible for cleanup. + + + + Forces the segment cleanup algorithm to be run. This method is intended + primarly for use from the Unit Test libraries. + + + + + Responsible for allocate 1 instance of an object that will be stored in a segment. + + An instance of whatever objec the pool is pooling. + + + + Checks in an instance of T owned by the object pool. This method is only intended to be called + by the WrappedObject class. + + The segment from which the instance is checked out. + The instance of T to check back into the segment. + + + + Checks an instance of T from the pool. If the pool is not sufficient to + allow the checkout, a new segment is created. + + A WrappedObject around the instance of T. To check + the instance back into the segment, be sureto dispose the WrappedObject + when finished. + + + + The total number of segments created. Intended to be used by the Unit Tests. + + + + + The number of items that are in a segment. Items in a segment + are all allocated at the same time, and are hopefully close to + each other in the managed heap. + + + + + The minimum number of segments. When segments are reclaimed, + this number of segments will always be left alone. These + segments are allocated at startup. + + + + + The age a segment must be before it's eligible for cleanup. + This is used to prevent thrash, and typical values are in + the 5 minute range. + + + + + The frequence which the cleanup thread runs. This is typically + expected to be in the 5 minute range. + + + + + Initialize the object pool in client mode + + Server to connect to + + + + + + Initialize the object pool in server mode + + + + + + + Returns a packet buffer with EndPoint set if the buffer is in + client mode, or with EndPoint set to null in server mode + + Initialized UDPPacketBuffer object + + + + Default constructor + + + + + Check a packet buffer out of the pool + + A packet buffer object + + + + Checks the instance back into the object pool + + + + + Returns an instance of the class that has been checked out of the Object Pool. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The ObservableDictionary class is used for storing key/value pairs. It has methods for firing + events to subscribers when items are added, removed, or changed. + + Key + Value + + + + A dictionary of callbacks to fire when specified action occurs + + + + + Register a callback to be fired when an action occurs + + The action + The callback to fire + + + + Unregister a callback + + The action + The callback to fire + + + + + + + + + + Internal dictionary that this class wraps around. Do not + modify or enumerate the contents of this dictionary without locking + + + + Initializes a new instance of the Class + with the specified key/value, has the default initial capacity. + + + + // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value. + public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(); + + + + + + Initializes a new instance of the Class + with the specified key/value, With its initial capacity specified. + + Initial size of dictionary + + + // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value, + // initially allocated room for 10 entries. + public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(10); + + + + + + Try to get entry from the with specified key + + Key to use for lookup + Value returned + if specified key exists, if not found + + + // find your avatar using the Simulator.ObjectsAvatars ObservableDictionary: + Avatar av; + if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) + Console.WriteLine("Found Avatar {0}", av.Name); + + + + + + + Finds the specified match. + + The match. + Matched value + + + // use a delegate to find a prim in the ObjectsPrimitives ObservableDictionary + // with the ID 95683496 + uint findID = 95683496; + Primitive findPrim = sim.ObjectsPrimitives.Find( + delegate(Primitive prim) { return prim.ID == findID; }); + + + + + Find All items in an + return matching items. + a containing found items. + + Find All prims within 20 meters and store them in a List + + int radius = 20; + List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( + delegate(Primitive prim) { + Vector3 pos = prim.Position; + return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); + } + ); + + + + + Find All items in an + return matching keys. + a containing found keys. + + Find All keys which also exist in another dictionary + + List<UUID> matches = myDict.FindAll( + delegate(UUID id) { + return myOtherDict.ContainsKey(id); + } + ); + + + + + Check if Key exists in Dictionary + Key to check for + if found, otherwise + + + Check if Value exists in Dictionary + Value to check for + if found, otherwise + + + + Adds the specified key to the dictionary, dictionary locking is not performed, + + + The key + The value + + + + Removes the specified key, dictionary locking is not performed + + The key. + if successful, otherwise + + + + Clear the contents of the dictionary + + + + + Enumerator for iterating dictionary entries + + + + + + Gets the number of Key/Value pairs contained in the + + + + + Indexer for the dictionary + + The key + The value + + + + Add a custom decoder callback + + The key of the field to decode + The custom decode handler + + + + Remove a custom decoder callback + + The key of the field to decode + The custom decode handler + + + + Creates a formatted string containing the values of a Packet + + The Packet + A formatted string of values of the nested items in the Packet object + + + + Decode an IMessage object into a beautifully formatted string + + The IMessage object + Recursion level (used for indenting) + A formatted string containing the names and values of the source object + + + + A custom decoder callback + + The key of the object + the data to decode + A string represending the fieldData + + + + Provides helper methods for parallelizing loops + + + + + Executes a for loop in which iterations may run in parallel + + The loop will be started at this index + The loop will be terminated before this index is reached + Method body to run for each iteration of the loop + + + + Executes a for loop in which iterations may run in parallel + + The number of concurrent execution threads to run + The loop will be started at this index + The loop will be terminated before this index is reached + Method body to run for each iteration of the loop + + + + Executes a foreach loop in which iterations may run in parallel + + Object type that the collection wraps + An enumerable collection to iterate over + Method body to run for each object in the collection + + + + Executes a foreach loop in which iterations may run in parallel + + Object type that the collection wraps + The number of concurrent execution threads to run + An enumerable collection to iterate over + Method body to run for each object in the collection + + + + Executes a series of tasks in parallel + + A series of method bodies to execute + + + + Executes a series of tasks in parallel + + The number of concurrent execution threads to run + A series of method bodies to execute + + + + Type of return to use when returning objects from a parcel + + + + + + + Return objects owned by parcel owner + + + Return objects set to group + + + Return objects not owned by parcel owner or set to group + + + Return a specific list of objects on parcel + + + Return objects that are marked for-sale + + + + Blacklist/Whitelist flags used in parcels Access List + + + + Agent is denied access + + + Agent is granted access + + + + The result of a request for parcel properties + + + + No matches were found for the request + + + Request matched a single parcel + + + Request matched multiple parcels + + + + Flags used in the ParcelAccessListRequest packet to specify whether + we want the access list (whitelist), ban list (blacklist), or both + + + + Request the access list + + + Request the ban list + + + Request both White and Black lists + + + + Sequence ID in ParcelPropertiesReply packets (sent when avatar + tries to cross a parcel border) + + + + Parcel is currently selected + + + Parcel restricted to a group the avatar is not a + member of + + + Avatar is banned from the parcel + + + Parcel is restricted to an access list that the + avatar is not on + + + Response to hovering over a parcel + + + + The tool to use when modifying terrain levels + + + + Level the terrain + + + Raise the terrain + + + Lower the terrain + + + Smooth the terrain + + + Add random noise to the terrain + + + Revert terrain to simulator default + + + + The tool size to use when changing terrain levels + + + + Small + + + Medium + + + Large + + + + Reasons agent is denied access to a parcel on the simulator + + + + Agent is not denied, access is granted + + + Agent is not a member of the group set for the parcel, or which owns the parcel + + + Agent is not on the parcels specific allow list + + + Agent is on the parcels ban list + + + Unknown + + + Agent is not age verified and parcel settings deny access to non age verified avatars + + + + Parcel overlay type. This is used primarily for highlighting and + coloring which is why it is a single integer instead of a set of + flags + + These values seem to be poorly thought out. The first three + bits represent a single value, not flags. For example Auction (0x05) is + not a combination of OwnedByOther (0x01) and ForSale(0x04). However, + the BorderWest and BorderSouth values are bit flags that get attached + to the value stored in the first three bits. Bits four, five, and six + are unused + + + Public land + + + Land is owned by another avatar + + + Land is owned by a group + + + Land is owned by the current avatar + + + Land is for sale + + + Land is being auctioned + + + Land is private + + + To the west of this area is a parcel border + + + To the south of this area is a parcel border + + + + Various parcel properties + + + + No flags set + + + Allow avatars to fly (a client-side only restriction) + + + Allow foreign scripts to run + + + This parcel is for sale + + + Allow avatars to create a landmark on this parcel + + + Allows all avatars to edit the terrain on this parcel + + + Avatars have health and can take damage on this parcel. + If set, avatars can be killed and sent home here + + + Foreign avatars can create objects here + + + All objects on this parcel can be purchased + + + Access is restricted to a group + + + Access is restricted to a whitelist + + + Ban blacklist is enabled + + + Unknown + + + List this parcel in the search directory + + + Allow personally owned parcels to be deeded to group + + + If Deeded, owner contributes required tier to group parcel is deeded to + + + Restrict sounds originating on this parcel to the + parcel boundaries + + + Objects on this parcel are sold when the land is + purchsaed + + + Allow this parcel to be published on the web + + + The information for this parcel is mature content + + + The media URL is an HTML page + + + The media URL is a raw HTML string + + + Restrict foreign object pushes + + + Ban all non identified/transacted avatars + + + Allow group-owned scripts to run + + + Allow object creation by group members or group + objects + + + Allow all objects to enter this parcel + + + Only allow group and owner objects to enter this parcel + + + Voice Enabled on this parcel + + + Use Estate Voice channel for Voice on this parcel + + + Deny Age Unverified Users + + + + Parcel ownership status + + + + Placeholder + + + Parcel is leased (owned) by an avatar or group + + + Parcel is in process of being leased (purchased) by an avatar or group + + + Parcel has been abandoned back to Governor Linden + + + + Category parcel is listed in under search + + + + No assigned category + + + Linden Infohub or public area + + + Adult themed area + + + Arts and Culture + + + Business + + + Educational + + + Gaming + + + Hangout or Club + + + Newcomer friendly + + + Parks and Nature + + + Residential + + + Shopping + + + Not Used? + + + Other + + + Not an actual category, only used for queries + + + + Type of teleport landing for a parcel + + + + Unset, simulator default + + + Specific landing point set for this parcel + + + No landing point set, direct teleports enabled for + this parcel + + + + Parcel Media Command used in ParcelMediaCommandMessage + + + + Stop the media stream and go back to the first frame + + + Pause the media stream (stop playing but stay on current frame) + + + Start the current media stream playing and stop when the end is reached + + + Start the current media stream playing, + loop to the beginning when the end is reached and continue to play + + + Specifies the texture to replace with video + If passing the key of a texture, it must be explicitly typecast as a key, + not just passed within double quotes. + + + Specifies the movie URL (254 characters max) + + + Specifies the time index at which to begin playing + + + Specifies a single agent to apply the media command to + + + Unloads the stream. While the stop command sets the texture to the first frame of the movie, + unload resets it to the real texture that the movie was replacing. + + + Turn on/off the auto align feature, similar to the auto align checkbox in the parcel media properties + (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter. + + + Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only). + Use "text/html" for HTML. + + + Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only). + This might still not be working + + + Sets a description for the media being displayed (1.19.1 RC0 and later only). + + + + Some information about a parcel of land returned from a DirectoryManager search + + + + Global Key of record + + + Parcel Owners + + + Name field of parcel, limited to 128 characters + + + Description field of parcel, limited to 256 characters + + + Total Square meters of parcel + + + Total area billable as Tier, for group owned land this will be 10% less than ActualArea + + + True of parcel is in Mature simulator + + + Grid global X position of parcel + + + Grid global Y position of parcel + + + Grid global Z position of parcel (not used) + + + Name of simulator parcel is located in + + + Texture of parcels display picture + + + Float representing calculated traffic based on time spent on parcel by avatars + + + Sale price of parcel (not used) + + + Auction ID of parcel + + + + Parcel Media Information + + + + A byte, if 0x1 viewer should auto scale media to fit object + + + A boolean, if true the viewer should loop the media + + + The Asset UUID of the Texture which when applied to a + primitive will display the media + + + A URL which points to any Quicktime supported media type + + + A description of the media + + + An Integer which represents the height of the media + + + An integer which represents the width of the media + + + A string which contains the mime type of the media + + + + Parcel of land, a portion of virtual real estate in a simulator + + + + The total number of contiguous 4x4 meter blocks your agent owns within this parcel + + + The total number of contiguous 4x4 meter blocks contained in this parcel owned by a group or agent other than your own + + + Deprecated, Value appears to always be 0 + + + Simulator-local ID of this parcel + + + UUID of the owner of this parcel + + + Whether the land is deeded to a group or not + + + + + + Date land was claimed + + + Appears to always be zero + + + This field is no longer used + + + Minimum corner of the axis-aligned bounding box for this + parcel + + + Maximum corner of the axis-aligned bounding box for this + parcel + + + Bitmap describing land layout in 4x4m squares across the + entire region + + + Total parcel land area + + + + + + Maximum primitives across the entire simulator owned by the same agent or group that owns this parcel that can be used + + + Total primitives across the entire simulator calculated by combining the allowed prim counts for each parcel + owned by the agent or group that owns this parcel + + + Maximum number of primitives this parcel supports + + + Total number of primitives on this parcel + + + For group-owned parcels this indicates the total number of prims deeded to the group, + for parcels owned by an individual this inicates the number of prims owned by the individual + + + Total number of primitives owned by the parcel group on + this parcel, or for parcels owned by an individual with a group set the + total number of prims set to that group. + + + Total number of prims owned by other avatars that are not set to group, or not the parcel owner + + + A bonus multiplier which allows parcel prim counts to go over times this amount, this does not affect + the max prims per simulator. e.g: 117 prim parcel limit x 1.5 bonus = 175 allowed + + + Autoreturn value in minutes for others' objects + + + + + + Sale price of the parcel, only useful if ForSale is set + The SalePrice will remain the same after an ownership + transfer (sale), so it can be used to see the purchase price after + a sale if the new owner has not changed it + + + Parcel Name + + + Parcel Description + + + URL For Music Stream + + + + + + Price for a temporary pass + + + How long is pass valid for + + + + + + Key of authorized buyer + + + Key of parcel snapshot + + + The landing point location + + + The landing point LookAt + + + The type of landing enforced from the enum + + + + + + + + + + + + Access list of who is whitelisted on this + parcel + + + Access list of who is blacklisted on this + parcel + + + TRUE of region denies access to age unverified users + + + true to obscure (hide) media url + + + true to obscure (hide) music url + + + A struct containing media details + + + + Displays a parcel object in string format + + string containing key=value pairs of a parcel object + + + + Defalt constructor + + Local ID of this parcel + + + + Update the simulator with any local changes to this Parcel object + + Simulator to send updates to + Whether we want the simulator to confirm + the update with a reply packet or not + + + + Set Autoreturn time + + Simulator to send the update to + + + + Parcel (subdivided simulator lots) subsystem + + + + The event subscribers. null if no subcribers + + + Raises the ParcelDwellReply event + A ParcelDwellReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the ParcelInfoReply event + A ParcelInfoReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the ParcelProperties event + A ParcelPropertiesEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the ParcelAccessListReply event + A ParcelAccessListReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the ParcelObjectOwnersReply event + A ParcelObjectOwnersReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the SimParcelsDownloaded event + A SimParcelsDownloadedEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the ForceSelectObjectsReply event + A ForceSelectObjectsReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the ParcelMediaUpdateReply event + A ParcelMediaUpdateReplyEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the ParcelMediaCommand event + A ParcelMediaCommandEventArgs object containing the + data returned from the simulator + + + Thread sync lock object + + + + Default constructor + + A reference to the GridClient object + + + + Request basic information for a single parcel + + Simulator-local ID of the parcel + + + + Request properties of a single parcel + + Simulator containing the parcel + Simulator-local ID of the parcel + An arbitrary integer that will be returned + with the ParcelProperties reply, useful for distinguishing between + multiple simultaneous requests + + + + Request the access list for a single parcel + + Simulator containing the parcel + Simulator-local ID of the parcel + An arbitrary integer that will be returned + with the ParcelAccessList reply, useful for distinguishing between + multiple simultaneous requests + + + + + Request properties of parcels using a bounding box selection + + Simulator containing the parcel + Northern boundary of the parcel selection + Eastern boundary of the parcel selection + Southern boundary of the parcel selection + Western boundary of the parcel selection + An arbitrary integer that will be returned + with the ParcelProperties reply, useful for distinguishing between + different types of parcel property requests + A boolean that is returned with the + ParcelProperties reply, useful for snapping focus to a single + parcel + + + + Request all simulator parcel properties (used for populating the Simulator.Parcels + dictionary) + + Simulator to request parcels from (must be connected) + + + + Request all simulator parcel properties (used for populating the Simulator.Parcels + dictionary) + + Simulator to request parcels from (must be connected) + If TRUE, will force a full refresh + Number of milliseconds to pause in between each request + + + + Request the dwell value for a parcel + + Simulator containing the parcel + Simulator-local ID of the parcel + + + + Send a request to Purchase a parcel of land + + The Simulator the parcel is located in + The parcels region specific local ID + true if this parcel is being purchased by a group + The groups + true to remove tier contribution if purchase is successful + The parcels size + The purchase price of the parcel + + + + + Reclaim a parcel of land + + The simulator the parcel is in + The parcels region specific local ID + + + + Deed a parcel to a group + + The simulator the parcel is in + The parcels region specific local ID + The groups + + + + Request prim owners of a parcel of land. + + Simulator parcel is in + The parcels region specific local ID + + + + Return objects from a parcel + + Simulator parcel is in + The parcels region specific local ID + the type of objects to return, + A list containing object owners s to return + + + + Subdivide (split) a parcel + + + + + + + + + + Join two parcels of land creating a single parcel + + + + + + + + + + Get a parcels LocalID + + Simulator parcel is in + Vector3 position in simulator (Z not used) + 0 on failure, or parcel LocalID on success. + A call to Parcels.RequestAllSimParcels is required to populate map and + dictionary. + + + + Terraform (raise, lower, etc) an area or whole parcel of land + + Simulator land area is in. + LocalID of parcel, or -1 if using bounding box + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + true on successful request sent. + Settings.STORE_LAND_PATCHES must be true, + Parcel information must be downloaded using RequestAllSimParcels() + + + + Terraform (raise, lower, etc) an area or whole parcel of land + + Simulator land area is in. + west border of area to modify + south border of area to modify + east border of area to modify + north border of area to modify + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + true on successful request sent. + Settings.STORE_LAND_PATCHES must be true, + Parcel information must be downloaded using RequestAllSimParcels() + + + + Terraform (raise, lower, etc) an area or whole parcel of land + + Simulator land area is in. + LocalID of parcel, or -1 if using bounding box + west border of area to modify + south border of area to modify + east border of area to modify + north border of area to modify + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + How many meters + or - to lower, 1 = 1 meter + true on successful request sent. + Settings.STORE_LAND_PATCHES must be true, + Parcel information must be downloaded using RequestAllSimParcels() + + + + Terraform (raise, lower, etc) an area or whole parcel of land + + Simulator land area is in. + LocalID of parcel, or -1 if using bounding box + west border of area to modify + south border of area to modify + east border of area to modify + north border of area to modify + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + How many meters + or - to lower, 1 = 1 meter + Height at which the terraform operation is acting at + + + + Sends a request to the simulator to return a list of objects owned by specific owners + + Simulator local ID of parcel + Owners, Others, Etc + List containing keys of avatars objects to select; + if List is null will return Objects of type selectType + Response data is returned in the event + + + + Eject and optionally ban a user from a parcel + + target key of avatar to eject + true to also ban target + + + + Freeze or unfreeze an avatar over your land + + target key to freeze + true to freeze, false to unfreeze + + + + Abandon a parcel of land + + Simulator parcel is in + Simulator local ID of parcel + + + + Requests the UUID of the parcel in a remote region at a specified location + + Location of the parcel in the remote region + Remote region handle + Remote region UUID + If successful UUID of the remote parcel, UUID.Zero otherwise + + + + Retrieves information on resources used by the parcel + + UUID of the parcel + Should per object resource usage be requested + Callback invoked when the request is complete + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a Parcel Update request + + + Raised when the parcel your agent is located sends a ParcelMediaCommand + + + + Parcel Accesslist + + + + Agents + + + + + + Flags for specific entry in white/black lists + + + + Owners of primitives on parcel + - + + Prim Owners + + + True of owner is group + + + Total count of prims owned by OwnerID + + + true of OwnerID is currently online and is not a group + + + The date of the most recent prim left by OwnerID + + - Update the properties of an object + Called once parcel resource usage information has been collected - The the object is located - The Local ID of the object - true to turn the objects physical property on - true to turn the objects temporary property on - true to turn the objects phantom property on - true to turn the objects cast shadows property on + Indicates if operation was successfull + Parcel resource usage information - + + Contains a parcels dwell data returned from the simulator in response to an + + - Update the properties of an object + Construct a new instance of the ParcelDwellReplyEventArgs class - The the object is located - The Local ID of the object - true to turn the objects physical property on - true to turn the objects temporary property on - true to turn the objects phantom property on - true to turn the objects cast shadows property on - Type of the represetnation prim will have in the physics engine - Density - normal value 1000 - Friction - normal value 0.6 - Restitution - standard value 0.5 - Gravity multiplier - standar value 1.0 + The global ID of the parcel + The simulator specific ID of the parcel + The calculated dwell for the parcel - + + Get the global ID of the parcel + + + Get the simulator specific ID of the parcel + + + Get the calculated dwell + + + Contains basic parcel information data returned from the + simulator in response to an request + + - Sets the sale properties of a single object + Construct a new instance of the ParcelInfoReplyEventArgs class - The the object is located - The Local ID of the object - One of the options from the enum - The price of the object + The object containing basic parcel info - + + Get the object containing basic parcel info + + + Contains basic parcel information data returned from the simulator in response to an request + + - Sets the sale properties of multiple objects - - The the objects are located - An array containing the Local IDs of the objects - One of the options from the enum - The price of the object + Construct a new instance of the ParcelPropertiesEventArgs class + + The object containing the details + The object containing the details + The result of the request + The number of primitieves your agent is + currently selecting and or sitting on in this parcel + The user assigned ID used to correlate a request with + these results + TODO: - + + Get the simulator the parcel is located in + + + Get the object containing the details + If Result is NoData, this object will not contain valid data + + + Get the result of the request + + + Get the number of primitieves your agent is + currently selecting and or sitting on in this parcel + + + Get the user assigned ID used to correlate a request with + these results + + + TODO: + + + Contains blacklist and whitelist data returned from the simulator in response to an request + + - Deselect a single object + Construct a new instance of the ParcelAccessListReplyEventArgs class - The the object is located - The Local ID of the object + The simulator the parcel is located in + The user assigned ID used to correlate a request with + these results + The simulator specific ID of the parcel + TODO: + The list containing the white/blacklisted agents for the parcel - + + Get the simulator the parcel is located in + + + Get the user assigned ID used to correlate a request with + these results + + + Get the simulator specific ID of the parcel + + + TODO: + + + Get the list containing the white/blacklisted agents for the parcel + + + Contains blacklist and whitelist data returned from the + simulator in response to an request + + - Deselect multiple objects. + Construct a new instance of the ParcelObjectOwnersReplyEventArgs class - The the objects are located - An array containing the Local IDs of the objects + The simulator the parcel is located in + The list containing prim ownership counts + + + Get the simulator the parcel is located in + + + Get the list containing prim ownership counts + + + Contains the data returned when all parcel data has been retrieved from a simulator + + + + Construct a new instance of the SimParcelsDownloadedEventArgs class + + The simulator the parcel data was retrieved from + The dictionary containing the parcel data + The multidimensional array containing a x,y grid mapped + to each 64x64 parcel's LocalID. + + + Get the simulator the parcel data was retrieved from + + + A dictionary containing the parcel data where the key correlates to the ParcelMap entry + + + Get the multidimensional array containing a x,y grid mapped + to each 64x64 parcel's LocalID. + + + Contains the data returned when a request + + + + Construct a new instance of the ForceSelectObjectsReplyEventArgs class + + The simulator the parcel data was retrieved from + The list of primitive IDs + true if the list is clean and contains the information + only for a given request + + + Get the simulator the parcel data was retrieved from + + + Get the list of primitive IDs + + + true if the list is clean and contains the information + only for a given request + + + Contains data when the media data for a parcel the avatar is on changes + + + + Construct a new instance of the ParcelMediaUpdateReplyEventArgs class + + the simulator the parcel media data was updated in + The updated media information + + + Get the simulator the parcel media data was updated in + + + Get the updated media information + + + Contains the media command for a parcel the agent is currently on + + + + Construct a new instance of the ParcelMediaCommandEventArgs class + + The simulator the parcel media command was issued in + + + The media command that was sent + + + + Get the simulator the parcel media command was issued in + + + + + + + + + Get the media command that was sent - - - Perform a click action on an object - - The the object is located - The Local ID of the object + + - + - Perform a click action (Grab) on a single object + - The the object is located - The Local ID of the object - The texture coordinates to touch - The surface coordinates to touch - The face of the position to touch - The region coordinates of the position to touch - The surface normal of the position to touch (A normal is a vector perpindicular to the surface) - The surface binormal of the position to touch (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space - + - Create (rez) a new prim object in a simulator + - A reference to the object to place the object in - Data describing the prim object to rez - Group ID that this prim will be set to, or UUID.Zero if you - do not want the object to be associated with a specific group - An approximation of the position at which to rez the prim - Scale vector to size this prim - Rotation quaternion to rotate this prim - Due to the way client prim rezzing is done on the server, - the requested position for an object is only close to where the prim - actually ends up. If you desire exact placement you'll need to - follow up by moving the object after it has been created. This - function will not set textures, light and flexible data, or other - extended primitive properties - + + + + + + + + + + + + + + + + + + + - Create (rez) a new prim object in a simulator + - A reference to the object to place the object in - Data describing the prim object to rez - Group ID that this prim will be set to, or UUID.Zero if you - do not want the object to be associated with a specific group - An approximation of the position at which to rez the prim - Scale vector to size this prim - Rotation quaternion to rotate this prim - Specify the - Due to the way client prim rezzing is done on the server, - the requested position for an object is only close to where the prim - actually ends up. If you desire exact placement you'll need to - follow up by moving the object after it has been created. This - function will not set textures, light and flexible data, or other - extended primitive properties - + - Rez a Linden tree + - A reference to the object where the object resides - The size of the tree - The rotation of the tree - The position of the tree - The Type of tree - The of the group to set the tree to, - or UUID.Zero if no group is to be set - true to use the "new" Linden trees, false to use the old - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Rez grass and ground cover + - A reference to the object where the object resides - The size of the grass - The rotation of the grass - The position of the grass - The type of grass from the enum - The of the group to set the tree to, - or UUID.Zero if no group is to be set - + + + + + + + + + + + + + - Set the textures to apply to the faces of an object + - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The texture data to apply + + - + - Set the textures to apply to the faces of an object + - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The texture data to apply - A media URL (not used) - + + + + + + + + + + + + + - Set the Light data on an object + - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set + + - + - Set the flexible data on an object + - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set - + + + + + + + + + + + + + + + + + + + - Set the sculptie texture and data on an object + - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set - + + + + + + + + + + + + + + + + - Unset additional primitive parameters on an object + - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The extra parameters to set + + - + - Link multiple prims into a linkset + - A reference to the object where the objects reside - An array which contains the IDs of the objects to link - The last object in the array will be the root object of the linkset TODO: Is this true? + + - + - Delink/Unlink multiple prims from a linkset + - A reference to the object where the objects reside - An array which contains the IDs of the objects to delink + + - + - Change the rotation of an object + - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new rotation of the object + + + - + - Set the name of an object + - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A string containing the new name of the object - + - Set the name of multiple objects + - A reference to the object where the objects reside - An array which contains the IDs of the objects to change the name of - An array which contains the new names of the objects + + - + - Set the description of an object + - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A string containing the new description of the object + + - + - Set the descriptions of multiple objects + - A reference to the object where the objects reside - An array which contains the IDs of the objects to change the description of - An array which contains the new descriptions of the objects + - + - Attach an object to this avatar + Class for controlling various system settings. - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The point on the avatar the object will be attached - The rotation of the attached object + Some values are readonly because they affect things that + happen when the GridClient object is initialized, so changing them at + runtime won't do any good. Non-readonly values may affect things that + happen at login or dynamically - - - Drop an attached object from this avatar - - A reference to the - object where the objects reside. This will always be the simulator the avatar is currently in - - The object's ID which is local to the simulator the object is in + + Main grid login server - - - Detach an object from yourself - - A reference to the - object where the objects reside - - This will always be the simulator the avatar is currently in - - An array which contains the IDs of the objects to detach + + Beta grid login server - + - Change the position of an object, Will change position of entire linkset + InventoryManager requests inventory information on login, + GridClient initializes an Inventory store for main inventory. - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new position of the object - + - Change the position of an object + InventoryManager requests library information on login, + GridClient initializes an Inventory store for the library. - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new position of the object - if true, will change position of (this) child prim only, not entire linkset - - - Change the Scale (size) of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new scale of the object - If true, will change scale of this prim only, not entire linkset - True to resize prims uniformly + + Number of milliseconds between sending pings to each sim - - - Change the Rotation of an object that is either a child or a whole linkset - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new scale of the object - If true, will change rotation of this prim only, not entire linkset + + Number of milliseconds between sending camera updates - - - Send a Multiple Object Update packet to change the size, scale or rotation of a primitive - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new rotation, size, or position of the target object - The flags from the Enum + + Number of milliseconds between updating the current + positions of moving, non-accelerating and non-colliding objects - - - Deed an object (prim) to a group, Object must be shared with group which - can be accomplished with SetPermissions() - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The of the group to deed the object to + + Millisecond interval between ticks, where all ACKs are + sent out and the age of unACKed packets is checked - - - Deed multiple objects (prims) to a group, Objects must be shared with group which - can be accomplished with SetPermissions() - - A reference to the object where the object resides - An array which contains the IDs of the objects to deed - The of the group to deed the object to + + The initial size of the packet inbox, where packets are + stored before processing - - - Set the permissions on multiple objects - - A reference to the object where the objects reside - An array which contains the IDs of the objects to set the permissions on - The new Who mask to set - Which permission to modify - The new state of permission + + Maximum size of packet that we want to send over the wire - + + The maximum value of a packet sequence number before it + rolls over back to one + + + The relative directory where external resources are kept + + + Login server to connect to + + + IP Address the client will bind to + + + Use XML-RPC Login or LLSD Login, default is XML-RPC Login + + - Request additional properties for an object + Maximum number of HTTP connections to open to a particular endpoint. - A reference to the object where the object resides - + + An endpoint is defined as a commbination of network address and port. This is used for Caps. + This is a static variable which applies to all instances. + - + - Request additional properties for an object + Use Caps for fetching inventory where available - A reference to the object where the object resides - Absolute UUID of the object - Whether to require server acknowledgement of this request - + + Number of milliseconds before an asset transfer will time + out + + + Number of milliseconds before a teleport attempt will time + out + + + Number of milliseconds before NetworkManager.Logout() will + time out + + + Number of milliseconds before a CAPS call will time out + Setting this too low will cause web requests time out and + possibly retry repeatedly + + + Number of milliseconds for xml-rpc to timeout + + + Milliseconds before a packet is assumed lost and resent + + + Milliseconds without receiving a packet before the + connection to a simulator is assumed lost + + + Milliseconds to wait for a simulator info request through + the grid interface + + + The maximum size of the sequence number archive, used to + check for resent and/or duplicate packets + + + Maximum number of queued ACKs to be sent before SendAcks() + is forced + + + Network stats queue length (seconds) + + - Set the ownership of a list of objects to the specified group + Primitives will be reused when falling in/out of interest list (and shared between clients) + prims returning to interest list do not need re-requested + Helps also in not re-requesting prim.Properties for code that checks for a Properties == null per client - A reference to the object where the objects reside - An array which contains the IDs of the objects to set the group id on - The Groups ID - + - Update current URL of the previously set prim media + Pool parcel data between clients (saves on requesting multiple times when all clients may need it) - UUID of the prim - Set current URL to this - Prim face number - Simulator in which prim is located - + - Set object media + How long to preserve cached data when no client is connected to a simulator + The reason for setting it to something like 2 minutes is in case a client + is running back and forth between region edges or a sim is comming and going - UUID of the prim - Array the length of prims number of faces. Null on face indexes where there is - no media, on faces which contain the media - Simulatior in which prim is located - - - Retrieve information about object media - - UUID of the primitive - Simulator where prim is located - Call this callback when done + + Enable/disable storing terrain heightmaps in the + TerrainManager - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Enable/disable sending periodic camera updates - - - A terse object update, used when a transformation matrix or - velocity/acceleration for an object changes but nothing else - (scale/position/rotation/acceleration/velocity) - - The sender - The EventArgs object containing the packet data + + Enable/disable automatically setting agent appearance at + login and after sim crossing - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Enable/disable automatically setting the bandwidth throttle + after connecting to each simulator + The default throttle uses the equivalent of the maximum + bandwidth setting in the official client. If you do not set a + throttle your connection will by default be throttled well below + the minimum values and you may experience connection problems - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Enable/disable the sending of pings to monitor lag and + packet loss - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Should we connect to multiple sims? This will allow + viewing in to neighboring simulators and sim crossings + (Experimental) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + If true, all object update packets will be decoded in to + native objects. If false, only updates for our own agent will be + decoded. Registering an event handler will force objects for that + type to always be decoded. If this is disabled the object tracking + will have missing or partial prim and avatar information - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + If true, when a cached object check is received from the + server the full object info will automatically be requested - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Whether to establish connections to HTTP capabilities + servers for simulators - - - - - - - + + Whether to decode sim stats - - - Setup construction data for a basic primitive shape - - Primitive shape to construct - Construction data that can be plugged into a + + The capabilities servers are currently designed to + periodically return a 502 error which signals for the client to + re-establish a connection. Set this to true to log those 502 errors - - - - - - - - + + If true, any reference received for a folder or item + the library is not aware of will automatically be fetched - - - - - - + + If true, and SEND_AGENT_UPDATES is true, + AgentUpdate packets will continuously be sent out to give the bot + smoother movement and autopiloting - - - Set the Shape data of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - Data describing the prim shape + + If true, currently visible avatars will be stored + in dictionaries inside Simulator.ObjectAvatars. + If false, a new Avatar or Primitive object will be created + each time an object update packet is received - + + If true, currently visible avatars will be stored + in dictionaries inside Simulator.ObjectPrimitives. + If false, a new Avatar or Primitive object will be created + each time an object update packet is received + + + If true, position and velocity will periodically be + interpolated (extrapolated, technically) for objects and + avatars that are being tracked by the library. This is + necessary to increase the accuracy of speed and position + estimates for simulated objects + + - Set the Material data of an object + If true, utilization statistics will be tracked. There is a minor penalty + in CPU time for enabling this option. - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new material of the object - + + If true, parcel details will be stored in the + Simulator.Parcels dictionary as they are received + + - + If true, an incoming parcel properties reply will automatically send + a request for the parcel access list - - - - - + - + if true, an incoming parcel properties reply will automatically send + a request for the traffic count. - - - - - - + - + If true, images, and other assets downloaded from the server + will be cached in a local directory - - - - - - - Raised when the simulator sends us data containing - A , Foliage or Attachment - - - - - Raised when the simulator sends us data containing - additional information - - - - - Raised when the simulator sends us data containing - Primitive.ObjectProperties for an object we are currently tracking - - - Raised when the simulator sends us data containing - additional and details - - - Raised when the simulator sends us data containing - updated information for an - - - Raised when the simulator sends us data containing - and movement changes + + Path to store cached texture data - - Raised when the simulator sends us data containing - updates to an Objects DataBlock + + Maximum size cached files are allowed to take on disk (bytes) - - Raised when the simulator informs us an - or is no longer within view + + Default color used for viewer particle effects - - Raised when the simulator informs us when a group of - or is no longer within view + + Maximum number of times to resend a failed packet - - Raised when the simulator sends us data containing - updated sit information for our + + Throttle outgoing packet rate - - Raised when the simulator sends us data containing - purchase price information for a + + UUID of a texture used by some viewers to indentify type of client used - - Raised when the simulator sends us data containing - additional information - - + + + Download textures using GetTexture capability when available + - + + The maximum number of concurrent texture downloads allowed + Increasing this number will not necessarily increase texture retrieval times due to + simulator throttles + + - Callback for getting object media data via CAP + The Refresh timer inteval is used to set the delay between checks for stalled texture downloads - Indicates if the operation was succesfull - Object media version string - Array indexed on prim face of media entry data + This is a static variable which applies to all instances - - Provides data for the event - The event occurs when the simulator sends - an containing a Primitive, Foliage or Attachment data - Note 1: The event will not be raised when the object is an Avatar - Note 2: It is possible for the to be - raised twice for the same object if for example the primitive moved to a new simulator, then returned to the current simulator or - if an Avatar crosses the border into a new simulator and returns to the current simulator - - - The following code example uses the , , and - properties to display new Primitives and Attachments on the window. - - // Subscribe to the event that gives us prim and foliage information - Client.Objects.ObjectUpdate += Objects_ObjectUpdate; - - - private void Objects_ObjectUpdate(object sender, PrimEventArgs e) - { - Console.WriteLine("Primitive {0} {1} in {2} is an attachment {3}", e.Prim.ID, e.Prim.LocalID, e.Simulator.Name, e.IsAttachment); - } - - - - - + + + Textures taking longer than this value will be flagged as timed out and removed from the pipeline + - + - Construct a new instance of the PrimEventArgs class + Get or set the minimum log level to output to the console by default + + If the library is not compiled with DEBUG defined and this level is set to DEBUG + You will get no output on the console. This behavior can be overriden by creating + a logger configuration file for log4net - The simulator the object originated from - The Primitive - The simulator time dilation - The prim was not in the dictionary before this update - true if the primitive represents an attachment to an agent - - Get the simulator the originated from + + Attach avatar names to log messages - - Get the details + + Log packet retransmission info - - true if the did not exist in the dictionary before this update (always true if object tracking has been disabled) + + Log disk cache misses and other info - - true if the is attached to an + + Constructor + Reference to a GridClient object - - Get the simulator Time Dilation + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Provides data for the event - The event occurs when the simulator sends - an containing Avatar data - Note 1: The event will not be raised when the object is an Avatar - Note 2: It is possible for the to be - raised twice for the same avatar if for example the avatar moved to a new simulator, then returned to the current simulator - - - The following code example uses the property to make a request for the top picks - using the method in the class to display the names - of our own agents picks listings on the window. - - // subscribe to the AvatarUpdate event to get our information - Client.Objects.AvatarUpdate += Objects_AvatarUpdate; - Client.Avatars.AvatarPicksReply += Avatars_AvatarPicksReply; - - private void Objects_AvatarUpdate(object sender, AvatarUpdateEventArgs e) - { - // we only want our own data - if (e.Avatar.LocalID == Client.Self.LocalID) - { - // Unsubscribe from the avatar update event to prevent a loop - // where we continually request the picks every time we get an update for ourselves - Client.Objects.AvatarUpdate -= Objects_AvatarUpdate; - // make the top picks request through AvatarManager - Client.Avatars.RequestAvatarPicks(e.Avatar.ID); - } - } - - private void Avatars_AvatarPicksReply(object sender, AvatarPicksReplyEventArgs e) - { - // we'll unsubscribe from the AvatarPicksReply event since we now have the data - // we were looking for - Client.Avatars.AvatarPicksReply -= Avatars_AvatarPicksReply; - // loop through the dictionary and extract the names of the top picks from our profile - foreach (var pickName in e.Picks.Values) - { - Console.WriteLine(pickName); - } - } - - - - + + Cost of uploading an asset + Read-only since this value is dynamically fetched at login - + - Construct a new instance of the AvatarUpdateEventArgs class + Simulator (region) properties - The simulator the packet originated from - The data - The simulator time dilation - The avatar was not in the dictionary before this update - - - Get the simulator the object originated from - - Get the data + + No flags set - - Get the simulator time dilation + + Agents can take damage and be killed - - true if the did not exist in the dictionary before this update (always true if avatar tracking has been disabled) + + Landmarks can be created here - - Provides additional primitive data for the event - The event occurs when the simulator sends - an containing additional details for a Primitive, Foliage data or Attachment data - The event is also raised when a request is - made. - - - The following code example uses the , and - - properties to display new attachments and send a request for additional properties containing the name of the - attachment then display it on the window. - - // Subscribe to the event that provides additional primitive details - Client.Objects.ObjectProperties += Objects_ObjectProperties; - - // handle the properties data that arrives - private void Objects_ObjectProperties(object sender, ObjectPropertiesEventArgs e) - { - Console.WriteLine("Primitive Properties: {0} Name is {1}", e.Properties.ObjectID, e.Properties.Name); - } - - + + Home position can be set in this sim - - - Construct a new instance of the ObjectPropertiesEventArgs class - - The simulator the object is located - The primitive Properties + + Home position is reset when an agent teleports away - - Get the simulator the object is located + + Sun does not move - - Get the primitive properties + + No object, land, etc. taxes - - Provides additional primitive data for the event - The event occurs when the simulator sends - an containing additional details for a Primitive or Foliage data that is currently - being tracked in the dictionary - The event is also raised when a request is - made and is enabled - + + Disable heightmap alterations (agents can still plant + foliage) - - - Construct a new instance of the ObjectPropertiesUpdatedEvenrArgs class - - The simulator the object is located - The Primitive - The primitive Properties + + Land cannot be released, sold, or purchased - - Get the primitive details + + All content is wiped nightly - - Provides additional primitive data, permissions and sale info for the event - The event occurs when the simulator sends - an containing additional details for a Primitive, Foliage data or Attachment. This includes - Permissions, Sale info, and other basic details on an object - The event is also raised when a request is - made, the viewer equivalent is hovering the mouse cursor over an object - + + Unknown: Related to the availability of an overview world map tile.(Think mainland images when zoomed out.) - - Get the simulator the object is located + + Unknown: Related to region debug flags. Possibly to skip processing of agent interaction with world. - - + + Region does not update agent prim interest lists. Internal debugging option. - - + + No collision detection for non-agent objects - - Provides primitive data containing updated location, velocity, rotation, textures for the event - The event occurs when the simulator sends updated location, velocity, rotation, etc - + + No scripts are ran - - Get the simulator the object is located + + All physics processing is turned off - - Get the primitive details + + Region can be seen from other regions on world map. (Legacy world map option?) - - + + Region can be seen from mainland on world map. (Legacy world map option?) - - + + Agents not explicitly on the access list can visit the region. - - - - + + Traffic calculations are not run across entire region, overrides parcel settings. - - Get the simulator the object is located + + Flight is disabled (not currently enforced by the sim) - - Get the primitive details + + Allow direct (p2p) teleporting - - + + Estate owner has temporarily disabled scripting - - + + Restricts the usage of the LSL llPushObject function, applies to whole region. - - + + Deny agents with no payment info on file - - + + Deny agents with payment info on file - - Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the - event + + Deny agents who have made a monetary transaction - - Get the simulator the object is located + + Parcels within the region may be joined or divided by anyone, not just estate owners/managers. - - The LocalID of the object + + Abuse reports sent from within this region are sent to the estate owner defined email. - - Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the - event + + Region is Voice Enabled - - Get the simulator the object is located + + Removes the ability from parcel owners to set their parcels to show in search. - - The LocalID of the object + + Deny agents who have not been age verified from entering the region. - + - Provides updates sit position data + Region protocol flags - - Get the simulator the object is located - - - + + Nothing special - - + + Region supports Server side Appearance - - + + Viewer supports Server side Appearance - + - + Access level for a simulator - - Get the simulator the object is located + + Unknown or invalid access level - - + + Trial accounts allowed - - + + PG rating - - + + Mature rating - + + Adult rating + + + Simulator is offline + + + Simulator does not exist + + - Indicates if the operation was successful + - + - Media version string + - + - Array of media entries indexed by face number + Initialize the UDP packet handler in server mode + Port to listening for incoming UDP packets on - + - Set when simulator sends us infomation on primitive's physical properties + Initialize the UDP packet handler in client mode + Remote UDP server to connect to - - Simulator where the message originated - - - Updated physical properties - - + - Constructor + - Simulator where the message originated - Updated physical properties - + - Manager class for our own avatar + - - The event subscribers. null if no subcribers - - - Raises the ChatFromSimulator event - A ChatEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - The event subscribers. null if no subcribers - - - Raises the ScriptDialog event - A SctriptDialogEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - The event subscribers. null if no subcribers - - - Raises the ScriptQuestion event - A ScriptQuestionEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - The event subscribers. null if no subcribers - - - Raises the LoadURL event - A LoadUrlEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - The event subscribers. null if no subcribers - - - Raises the MoneyBalance event - A BalanceEventArgs object containing the - data returned from the data server - - - Thread sync lock object + + + + - - The event subscribers. null if no subcribers + + A public reference to the client that this Simulator object + is attached to - - Raises the MoneyBalanceReply event - A MoneyBalanceReplyEventArgs object containing the - data returned from the data server + + A Unique Cache identifier for this simulator - - Thread sync lock object + + The capabilities for this simulator - - The event subscribers. null if no subcribers + + - - Raises the IM event - A InstantMessageEventArgs object containing the - data returned from the data server + + The current version of software this simulator is running - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + A 64x64 grid of parcel coloring values. The values stored + in this array are of the type - - Raises the TeleportProgress event - A TeleportEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the AgentDataReply event - A AgentDataReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the AnimationsChanged event - A AnimationsChangedEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the MeanCollision event - A MeanCollisionEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the RegionCrossed event - A RegionCrossedEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupChatJoined event - A GroupChatJoinedEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the AlertMessage event - A AlertMessageEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + true if your agent has Estate Manager rights on this region - - The event subscribers. null if no subcribers + + - - Raises the ScriptControlChange event - A ScriptControlEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + Statistics information for this simulator and the + connection to the simulator, calculated by the simulator itself + and the library - - Raises the CameraConstraint event - A CameraConstraintEventArgs object containing the - data returned from the data server + + The regions Unique ID - - Thread sync lock object + + The physical data center the simulator is located + Known values are: + + Dallas + Chandler + SF + + - - The event subscribers. null if no subcribers + + The CPU Class of the simulator + Most full mainland/estate sims appear to be 5, + Homesteads and Openspace appear to be 501 - - Raises the ScriptSensorReply event - A ScriptSensorReplyEventArgs object containing the - data returned from the data server + + The number of regions sharing the same CPU as this one + "Full Sims" appear to be 1, Homesteads appear to be 4 - - Thread sync lock object + + The billing product name + Known values are: + + Mainland / Full Region (Sku: 023) + Estate / Full Region (Sku: 024) + Estate / Openspace (Sku: 027) + Estate / Homestead (Sku: 029) + Mainland / Homestead (Sku: 129) (Linden Owned) + Mainland / Linden Homes (Sku: 131) + + - - The event subscribers. null if no subcribers + + The billing product SKU + Known values are: + + 023 Mainland / Full Region + 024 Estate / Full Region + 027 Estate / Openspace + 029 Estate / Homestead + 129 Mainland / Homestead (Linden Owned) + 131 Linden Homes / Full Region + + - - Raises the AvatarSitResponse event - A AvatarSitResponseEventArgs object containing the - data returned from the data server + + + Flags indicating which protocols this region supports + - - Thread sync lock object + + The current sequence number for packets sent to this + simulator. Must be Interlocked before modifying. Only + useful for applications manipulating sequence numbers - - The event subscribers. null if no subcribers + + + A thread-safe dictionary containing avatars in a simulator + - - Raises the ChatSessionMemberAdded event - A ChatSessionMemberAddedEventArgs object containing the - data returned from the data server + + + A thread-safe dictionary containing primitives in a simulator + - - Thread sync lock object + + + Checks simulator parcel map to make sure it has downloaded all data successfully + + true if map is full (contains no 0's) - - The event subscribers. null if no subcribers + + + Is it safe to send agent updates to this sim + AgentMovementComplete message received + - - Raises the ChatSessionMemberLeft event - A ChatSessionMemberLeftEventArgs object containing the - data returned from the data server + + Used internally to track sim disconnections - - Thread sync lock object + + Event that is triggered when the simulator successfully + establishes a connection - - The event subscribers, null of no subscribers + + Whether this sim is currently connected or not. Hooked up + to the property Connected - - Raises the SetDisplayNameReply Event - A SetDisplayNameReplyEventArgs object containing - the data sent from the simulator + + Coarse locations of avatars in this simulator - - Thread sync lock object + + AvatarPositions key representing TrackAgent target - - The event subscribers. null if no subcribers + + Sequence numbers of packets we've received + (for duplicate checking) - - Raises the MuteListUpdated event - A EventArgs object containing the - data returned from the data server + + Packets we sent out that need ACKs from the simulator - - Thread sync lock object + + Sequence number for pause/resume - - Reference to the GridClient instance + + Indicates if UDP connection to the sim is fully established + + + + + + Reference to the GridClient object + IPEndPoint of the simulator + handle of the simulator - - Used for movement and camera tracking + + + Called when this Simulator object is being destroyed + - - Currently playing animations for the agent. Can be used to - check the current movement status such as walking, hovering, aiming, - etc. by checking against system animations found in the Animations class + + + Attempt to connect to this simulator + + Whether to move our agent in to this sim or not + True if the connection succeeded or connection status is + unknown, false if there was a failure - - Dictionary containing current Group Chat sessions and members + + + Initiates connection to the simulator + + Should we block until ack for this packet is recieved - - Dictionary containing mute list keyead on mute name and key + + + Disconnect from this simulator + - - Various abilities and preferences sent by the grid + + + Instructs the simulator to stop sending update (and possibly other) packets + - + - Constructor, setup callbacks for packets related to our avatar + Instructs the simulator to resume sending update packets (unpause) - A reference to the Class - + - Send a text message from the Agent to the Simulator + Retrieve the terrain height at a given coordinate - A containing the message - The channel to send the message on, 0 is the public channel. Channels above 0 - can be used however only scripts listening on the specified channel will see the message - Denotes the type of message being sent, shout, whisper, etc. + Sim X coordinate, valid range is from 0 to 255 + Sim Y coordinate, valid range is from 0 to 255 + The terrain height at the given point if the + lookup was successful, otherwise 0.0f + True if the lookup was successful, otherwise false - + - Request any instant messages sent while the client was offline to be resent. + Sends a packet + Packet to be sent - + - Send an Instant Message to another Avatar + - The recipients - A containing the message to send - + - Send an Instant Message to an existing group chat or conference chat + Returns Simulator Name as a String - The recipients - A containing the message to send - IM session ID (to differentiate between IM windows) + - + - Send an Instant Message + - The name this IM will show up as being from - Key of Avatar - Text message being sent - IM session ID (to differentiate between IM windows) - IDs of sessions for a conference + - + - Send an Instant Message + - The name this IM will show up as being from - Key of Avatar - Text message being sent - IM session ID (to differentiate between IM windows) - Type of instant message to send - Whether to IM offline avatars as well - Senders Position - RegionID Sender is In - Packed binary data that is specific to - the dialog type + + - + - Send an Instant Message to a group + Sends out pending acknowledgements - of the group to send message to - Text Message being sent. + Number of ACKs sent - + - Send an Instant Message to a group the agent is a member of + Resend unacknowledged packets - The name this IM will show up as being from - of the group to send message to - Text message being sent - + - Send a request to join a group chat session + Provides access to an internal thread-safe dictionary containing parcel + information found in this simulator - of Group to leave - + - Exit a group chat session. This will stop further Group chat messages - from being sent until session is rejoined. + Provides access to an internal thread-safe multidimensional array containing a x,y grid mapped + to each 64x64 parcel's LocalID. - of Group chat session to leave - + + The IP address and port of the server + + + Whether there is a working connection to the simulator or + not + + + Coarse locations of avatars in this simulator + + + AvatarPositions key representing TrackAgent target + + + Indicates if UDP connection to the sim is fully established + + - Reply to script dialog questions. + Simulator Statistics - Channel initial request came on - Index of button you're "clicking" - Label of button you're "clicking" - of Object that sent the dialog request - - + + Total number of packets sent by this simulator to this agent + + + Total number of packets received by this simulator to this agent + + + Total number of bytes sent by this simulator to this agent + + + Total number of bytes received by this simulator to this agent + + + Time in seconds agent has been connected to simulator + + + Total number of packets that have been resent + + + Total number of resent packets recieved + + + Total number of pings sent to this simulator by this agent + + + Total number of ping replies sent to this agent by this simulator + + - Accept invite for to a chatterbox session + Incoming bytes per second - of session to accept invite to + It would be nice to have this claculated on the fly, but + this is far, far easier - + - Start a friends conference + Outgoing bytes per second - List of UUIDs to start a conference with - the temportary session ID returned in the callback> + It would be nice to have this claculated on the fly, but + this is far, far easier + + + Time last ping was sent + + + ID of last Ping sent + + + + + + + + + Current time dilation of this simulator + + + Current Frames per second of simulator + + + Current Physics frames per second of simulator + + + + + + + + + + + + + + + + + + + + + + + + + + + Total number of objects Simulator is simulating + + + Total number of Active (Scripted) objects running + + + Number of agents currently in this simulator + + + Number of agents in neighbor simulators - - - Start a particle stream between an agent and an object - - Key of the source agent - Key of the target object - - The type from the enum - A unique for this effect + + Number of Active scripts running in this simulator - - - Start a particle stream between an agent and an object - - Key of the source agent - Key of the target object - A representing the beams offset from the source - A which sets the avatars lookat animation - of the Effect + + - - - Create a particle beam between an avatar and an primitive - - The ID of source avatar - The ID of the target primitive - global offset - A object containing the combined red, green, blue and alpha - color values of particle beam - a float representing the duration the parcicle beam will last - A Unique ID for the beam - + + - - - Create a particle swirl around a target position using a packet - - global offset - A object containing the combined red, green, blue and alpha - color values of particle beam - a float representing the duration the parcicle beam will last - A Unique ID for the beam + + - - - Sends a request to sit on the specified object - - of the object to sit on - Sit at offset + + Number of downloads pending - - - Follows a call to to actually sit on the object - + + Number of uploads pending - - Stands up from sitting on a prim or the ground - true of AgentUpdate was sent + + - - - Does a "ground sit" at the avatar's current position - + + - - - Starts or stops flying - - True to start flying, false to stop flying + + Number of local uploads pending - - - Starts or stops crouching - - True to start crouching, false to stop crouching + + Unacknowledged bytes in queue - + - Starts a jump (begin holding the jump key) + Simulator handle - + - Use the autopilot sim function to move the avatar to a new - position. Uses double precision to get precise movements + Number of GridClients using this datapool - The z value is currently not handled properly by the simulator - Global X coordinate to move to - Global Y coordinate to move to - Z coordinate to move to - + - Use the autopilot sim function to move the avatar to a new position + Time that the last client disconnected from the simulator - The z value is currently not handled properly by the simulator - Integer value for the global X coordinate to move to - Integer value for the global Y coordinate to move to - Floating-point value for the Z coordinate to move to - + - Use the autopilot sim function to move the avatar to a new position + The cache of prims used and unused in this simulator - The z value is currently not handled properly by the simulator - Integer value for the local X coordinate to move to - Integer value for the local Y coordinate to move to - Floating-point value for the Z coordinate to move to - - - Macro to cancel autopilot sim function - Not certain if this is how it is really done - true if control flags were set and AgentUpdate was sent to the simulator - + - Grabs an object + Shared parcel info only when POOL_PARCEL_DATA == true - an unsigned integer of the objects ID within the simulator - - + - Overload: Grab a simulated object + - an unsigned integer of the objects ID within the simulator - - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space - - - Drag an object - - of the object to drag - Drag target in region coordinates + + The event subscribers, null of no subscribers - - - Overload: Drag an object - - of the object to drag - Drag target in region coordinates - - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space + + Raises the AttachedSound Event + A AttachedSoundEventArgs object containing + the data sent from the simulator - - - Release a grabbed object - - The Objects Simulator Local ID - - - + + Thread sync lock object - - - Release a grabbed object - - The Objects Simulator Local ID - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space + + The event subscribers, null of no subscribers - - - Touches an object - - an unsigned integer of the objects ID within the simulator - + + Raises the AttachedSoundGainChange Event + A AttachedSoundGainChangeEventArgs object containing + the data sent from the simulator - - - Request the current L$ balance - + + Thread sync lock object - - - Give Money to destination Avatar - - UUID of the Target Avatar - Amount in L$ + + The event subscribers, null of no subscribers - - - Give Money to destination Avatar - - UUID of the Target Avatar - Amount in L$ - Description that will show up in the - recipients transaction history + + Raises the SoundTrigger Event + A SoundTriggerEventArgs object containing + the data sent from the simulator - - - Give L$ to an object - - object to give money to - amount of L$ to give - name of object + + Thread sync lock object - - - Give L$ to a group - - group to give money to - amount of L$ to give + + The event subscribers, null of no subscribers - - - Give L$ to a group - - group to give money to - amount of L$ to give - description of transaction + + Raises the PreloadSound Event + A PreloadSoundEventArgs object containing + the data sent from the simulator + + + Thread sync lock object - + - Pay texture/animation upload fee + Construct a new instance of the SoundManager class, used for playing and receiving + sound assets + A reference to the current GridClient instance - + - Pay texture/animation upload fee + Plays a sound in the current region at full volume from avatar position - description of the transaction + UUID of the sound to be played - + - Give Money to destination Object or Avatar + Plays a sound in the current region at full volume - UUID of the Target Object/Avatar - Amount in L$ - Reason (Optional normally) - The type of transaction - Transaction flags, mostly for identifying group - transactions + UUID of the sound to be played. + position for the sound to be played at. Normally the avatar. - + - Plays a gesture + Plays a sound in the current region - Asset of the gesture + UUID of the sound to be played. + position for the sound to be played at. Normally the avatar. + volume of the sound, from 0.0 to 1.0 - + - Mark gesture active + Plays a sound in the specified sim - Inventory of the gesture - Asset of the gesture + UUID of the sound to be played. + UUID of the sound to be played. + position for the sound to be played at. Normally the avatar. + volume of the sound, from 0.0 to 1.0 - + - Mark gesture inactive + Play a sound asset - Inventory of the gesture + UUID of the sound to be played. + handle id for the sim to be played in. + position for the sound to be played at. Normally the avatar. + volume of the sound, from 0.0 to 1.0 - - - Send an AgentAnimation packet that toggles a single animation on - - The of the animation to start playing - Whether to ensure delivery of this packet or not + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Send an AgentAnimation packet that toggles a single animation off - - The of a - currently playing animation to stop playing - Whether to ensure delivery of this packet or not + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Send an AgentAnimation packet that will toggle animations on or off - - A list of animation s, and whether to - turn that animation on or off - Whether to ensure delivery of this packet or not + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Teleports agent to their stored home location - - true on successful teleport to home location + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Teleport agent to a landmark - - of the landmark to teleport agent to - true on success, false on failure + + Raised when the simulator sends us data containing + sound - - - Attempt to look up a simulator name and teleport to the discovered - destination - - Region name to look up - Position to teleport to - True if the lookup and teleport were successful, otherwise - false + + Raised when the simulator sends us data containing + ... - - - Attempt to look up a simulator name and teleport to the discovered - destination - - Region name to look up - Position to teleport to - Target to look at - True if the lookup and teleport were successful, otherwise - false + + Raised when the simulator sends us data containing + ... - - - Teleport agent to another region - - handle of region to teleport agent to - position in destination sim to teleport to - true on success, false on failure - This call is blocking + + Raised when the simulator sends us data containing + ... - + + Provides data for the event + The event occurs when the simulator sends + the sound data which emits from an agents attachment + + The following code example shows the process to subscribe to the event + and a stub to handle the data passed from the simulator + + // Subscribe to the AttachedSound event + Client.Sound.AttachedSound += Sound_AttachedSound; + + // process the data raised in the event here + private void Sound_AttachedSound(object sender, AttachedSoundEventArgs e) + { + // ... Process AttachedSoundEventArgs here ... + } + + + + - Teleport agent to another region + Construct a new instance of the SoundTriggerEventArgs class - handle of region to teleport agent to - position in destination sim to teleport to - direction in destination sim agent will look at - true on success, false on failure - This call is blocking + Simulator where the event originated + The sound asset id + The ID of the owner + The ID of the object + The volume level + The - + + Simulator where the event originated + + + Get the sound asset id + + + Get the ID of the owner + + + Get the ID of the Object + + + Get the volume level + + + Get the + + + Provides data for the event + The event occurs when an attached sound + changes its volume level + + - Request teleport to a another simulator + Construct a new instance of the AttachedSoundGainChangedEventArgs class - handle of region to teleport agent to - position in destination sim to teleport to + Simulator where the event originated + The ID of the Object + The new volume level - + + Simulator where the event originated + + + Get the ID of the Object + + + Get the volume level + + + Provides data for the event + The event occurs when the simulator forwards + a request made by yourself or another agent to play either an asset sound or a built in sound + + Requests to play sounds where the is not one of the built-in + will require sending a request to download the sound asset before it can be played + + + The following code example uses the , + and + properties to display some information on a sound request on the window. + + // subscribe to the event + Client.Sound.SoundTrigger += Sound_SoundTrigger; + + // play the pre-defined BELL_TING sound + Client.Sound.SendSoundTrigger(Sounds.BELL_TING); + + // handle the response data + private void Sound_SoundTrigger(object sender, SoundTriggerEventArgs e) + { + Console.WriteLine("{0} played the sound {1} at volume {2}", + e.OwnerID, e.SoundID, e.Gain); + } + + + + - Request teleport to a another simulator + Construct a new instance of the SoundTriggerEventArgs class - handle of region to teleport agent to - position in destination sim to teleport to - direction in destination sim agent will look at + Simulator where the event originated + The sound asset id + The ID of the owner + The ID of the object + The ID of the objects parent + The volume level + The regionhandle + The source position - - - Teleport agent to a landmark - - of the landmark to teleport agent to + + Simulator where the event originated - - - Send a teleport lure to another avatar with default "Join me in ..." invitation message - - target avatars to lure + + Get the sound asset id - - - Send a teleport lure to another avatar with custom invitation message - - target avatars to lure - custom message to send with invitation + + Get the ID of the owner - - - Respond to a teleport lure by either accepting it and initiating - the teleport, or denying it - - of the avatar sending the lure - IM session of the incoming lure request - true to accept the lure, false to decline it + + Get the ID of the Object - - - Update agent profile - - struct containing updated - profile information + + Get the ID of the objects parent - - - Update agents profile interests - - selection of interests from struct + + Get the volume level - - - Set the height and the width of the client window. This is used - by the server to build a virtual camera frustum for our avatar - - New height of the viewer window - New width of the viewer window + + Get the regionhandle - - - Request the list of muted objects and avatars for this agent - + + Get the source position - - - Mute an object, resident, etc. - - Mute type - Mute UUID - Mute name + + Provides data for the event + The event occurs when the simulator sends + the appearance data for an avatar + + The following code example uses the and + properties to display the selected shape of an avatar on the window. + + // subscribe to the event + Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; + + // handle the data when the event is raised + void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) + { + Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") + } + + - + - Mute an object, resident, etc. + Construct a new instance of the PreloadSoundEventArgs class - Mute type - Mute UUID - Mute name - Mute flags + Simulator where the event originated + The sound asset id + The ID of the owner + The ID of the object - - - Unmute an object, resident, etc. - - Mute UUID - Mute name + + Simulator where the event originated - - - Sets home location to agents current position - - will fire an AlertMessage () with - success or failure message + + Get the sound asset id - - - Move an agent in to a simulator. This packet is the last packet - needed to complete the transition in to a new simulator - - Object + + Get the ID of the owner - - - Reply to script permissions request - - Object - of the itemID requesting permissions - of the taskID requesting permissions - list of permissions to allow + + Get the ID of the Object - + - Respond to a group invitation by either accepting or denying it + pre-defined built in sounds - UUID of the group (sent in the AgentID field of the invite message) - IM Session ID from the group invitation message - Accept the group invitation or deny it - - - Requests script detection of objects and avatars - - name of the object/avatar to search for - UUID of the object or avatar to search for - Type of search from ScriptSensorTypeFlags - range of scan (96 max?) - the arc in radians to search within - an user generated ID to correlate replies with - Simulator to perform search in + + - - - Create or update profile pick - - UUID of the pick to update, or random UUID to create a new pick - Is this a top pick? (typically false) - UUID of the parcel (UUID.Zero for the current parcel) - Name of the pick - Global position of the pick landmark - UUID of the image displayed with the pick - Long description of the pick + + - - - Delete profile pick - - UUID of the pick to delete + + - - - Create or update profile Classified - - UUID of the classified to update, or random UUID to create a new classified - Defines what catagory the classified is in - UUID of the image displayed with the classified - Price that the classified will cost to place for a week - Global position of the classified landmark - Name of the classified - Long description of the classified - if true, auto renew classified after expiration + + - - - Create or update profile Classified - - UUID of the classified to update, or random UUID to create a new classified - Defines what catagory the classified is in - UUID of the image displayed with the classified - Price that the classified will cost to place for a week - Name of the classified - Long description of the classified - if true, auto renew classified after expiration + + - - - Delete a classified ad - - The classified ads ID + + - - - Fetches resource usage by agents attachmetns - - Called when the requested information is collected + + - - - Initates request to set a new display name - - Previous display name - Desired new display name + + - - - Tells the sim what UI language is used, and if it's ok to share that with scripts - - Two letter language code - Share language info with scripts + + coins - - - Take an incoming ImprovedInstantMessage packet, auto-parse, and if - OnInstantMessage is defined call that with the appropriate arguments - - The sender - The EventArgs object containing the packet data + + cash register bell - - - Take an incoming Chat packet, auto-parse, and if OnChat is defined call - that with the appropriate arguments. - - The sender - The EventArgs object containing the packet data + + - - - Used for parsing llDialogs - - The sender - The EventArgs object containing the packet data + + - - - Used for parsing llRequestPermissions dialogs - - The sender - The EventArgs object containing the packet data + + rubber - - - Handles Script Control changes when Script with permissions releases or takes a control - - The sender - The EventArgs object containing the packet data + + plastic - - - Used for parsing llLoadURL Dialogs - - The sender - The EventArgs object containing the packet data + + flesh - - - Update client's Position, LookAt and region handle from incoming packet - - The sender - The EventArgs object containing the packet data - This occurs when after an avatar moves into a new sim + + wood splintering? - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + glass break - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + metal clunk - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + whoosh - - - EQ Message fired with the result of SetDisplayName request - - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet + + shake - - - Process TeleportFailed message sent via EventQueue, informs agent its last teleport has failed and why. - - The Message Key - An IMessage object Deserialized from the recieved message event - The simulator originating the event message + + - - - Process TeleportFinish from Event Queue and pass it onto our TeleportHandler - - The message system key for this event - IMessage object containing decoded data from OSD - The simulator originating the event message + + ding - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - - Crossed region handler for message that comes across the EventQueue. Sent to an agent - when the agent crosses a sim border into a new region. - - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - This packet is now being sent via the EventQueue + + - - - Group Chat event handler - - The capability Key - IMessage object containing decoded data from OSD - + + - - - Response from request to join a group chat - - - IMessage object containing decoded data from OSD - + + - - - Someone joined or left group chat - - - IMessage object containing decoded data from OSD - + + - - - Handle a group chat Invitation - - Caps Key - IMessage object containing decoded data from OSD - Originating Simulator + + - - - Moderate a chat session - - the of the session to moderate, for group chats this will be the groups UUID - the of the avatar to moderate - Either "voice" to moderate users voice, or "text" to moderate users text session - true to moderate (silence user), false to allow avatar to speak + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Raised when a scripted object or agent within range sends a public message + + + A dictionary containing all pre-defined sounds + + A dictionary containing the pre-defined sounds, + where the key is the sounds ID, and the value is a string + containing a name to identify the purpose of the sound - - Raised when a scripted object sends a dialog box containing possible - options an agent can respond to + + X position of this patch - - Raised when an object requests a change in the permissions an agent has permitted + + Y position of this patch - - Raised when a script requests an agent open the specified URL + + A 16x16 array of floats holding decompressed layer data - - Raised when an agents currency balance is updated + + + Creates a LayerData packet for compressed land data given a full + simulator heightmap and an array of indices of patches to compress + + A 256 * 256 array of floating point values + specifying the height at each meter in the simulator + Array of indexes in the 16x16 grid of patches + for this simulator. For example if 1 and 17 are specified, patches + x=1,y=0 and x=1,y=1 are sent + - - Raised when a transaction occurs involving currency such as a land purchase + + + Add a patch of terrain to a BitPacker + + BitPacker to write the patch to + Heightmap of the simulator, must be a 256 * + 256 float array + X offset of the patch to create, valid values are + from 0 to 15 + Y offset of the patch to create, valid values are + from 0 to 15 - - Raised when an ImprovedInstantMessage packet is recieved from the simulator, this is used for everything from - private messaging to friendship offers. The Dialog field defines what type of message has arrived + + The event subscribers. null if no subcribers - - Raised when an agent has requested a teleport to another location, or when responding to a lure. Raised multiple times - for each teleport indicating the progress of the request + + Raises the LandPatchReceived event + A LandPatchReceivedEventArgs object containing the + data returned from the simulator - - Raised when a simulator sends agent specific information for our avatar. + + Thread sync lock object - - Raised when our agents animation playlist changes + + + Default constructor + + + + + Raised when the simulator responds sends - - Raised when an object or avatar forcefully collides with our agent + + Simulator from that sent tha data - - Raised when our agent crosses a region border into another region + + Sim coordinate of the patch - - Raised when our agent succeeds or fails to join a group chat session + + Sim coordinate of the patch - - Raised when a simulator sends an urgent message usually indication the recent failure of - another action we have attempted to take such as an attempt to enter a parcel where we are denied access + + Size of tha patch - - Raised when a script attempts to take or release specified controls for our agent + + Heightmap for the patch - - Raised when the simulator detects our agent is trying to view something - beyond its limits + + + The current status of a texture request as it moves through the pipeline or final result of a texture request. + - - Raised when a script sensor reply is received from a simulator + + The initial state given to a request. Requests in this state + are waiting for an available slot in the pipeline - - Raised in response to a request + + A request that has been added to the pipeline and the request packet + has been sent to the simulator - - Raised when an avatar enters a group chat session we are participating in + + A request that has received one or more packets back from the simulator - - Raised when an agent exits a group chat session we are participating in + + A request that has received all packets back from the simulator - - Raised when the simulator sends us data containing - the details of display name change + + A request that has taken longer than + to download OR the initial packet containing the packet information was never received - - Raised when a scripted object or agent within range sends a public message + + The texture request was aborted by request of the agent - - Your (client) avatars - "client", "agent", and "avatar" all represent the same thing + + The simulator replied to the request that it was not able to find the requested texture - - Temporary assigned to this session, used for - verifying our identity in packets + + + A callback fired to indicate the status or final state of the requested texture. For progressive + downloads this will fire each time new asset data is returned from the simulator. + + The indicating either Progress for textures not fully downloaded, + or the final result of the request after it has been processed through the TexturePipeline + The object containing the Assets ID, raw data + and other information. For progressive rendering the will contain + the data from the beginning of the file. For failed, aborted and timed out requests it will contain + an empty byte array. - - Shared secret that is never sent over the wire + + + Texture request download handler, allows a configurable number of download slots which manage multiple + concurrent texture downloads from the + + This class makes full use of the internal + system for full texture downloads. - - Your (client) avatar ID, local to the current region/sim + + A dictionary containing all pending and in-process transfer requests where the Key is both the RequestID + and also the Asset Texture ID, and the value is an object containing the current state of the request and also + the asset data as it is being re-assembled - - Where the avatar started at login. Can be "last", "home" - or a login + + Holds the reference to the client object - - The access level of this agent, usually M or PG + + Maximum concurrent texture requests allowed at a time - - The CollisionPlane of Agent + + An array of objects used to manage worker request threads - - An representing the velocity of our agent + + An array of worker slots which shows the availablity status of the slot - - An representing the acceleration of our agent + + The primary thread which manages the requests. - - A which specifies the angular speed, and axis about which an Avatar is rotating. + + true if the TexturePipeline is currently running - - Position avatar client will goto when login to 'home' or during - teleport request to 'home' region. + + A synchronization object used by the primary thread - - LookAt point saved/restored with HomePosition + + A refresh timer used to increase the priority of stalled requests - - Avatar First Name (i.e. Philip) + + + Default constructor, Instantiates a new copy of the TexturePipeline class + + Reference to the instantiated object - - Avatar Last Name (i.e. Linden) + + + Initialize callbacks required for the TexturePipeline to operate + - - Avatar Full Name (i.e. Philip Linden) + + + Shutdown the TexturePipeline and cleanup any callbacks or transfers + - - Gets the health of the agent + + + Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + A float indicating the requested priority for the transfer. Higher priority values tell the simulator + to prioritize the request before lower valued requests. An image already being transferred using the can have + its priority changed by resending the request with the new priority value + Number of quality layers to discard. + This controls the end marker of the data sent + The packet number to begin the request at. A value of 0 begins the request + from the start of the asset texture + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + If true, the callback will be fired for each chunk of the downloaded image. + The callback asset parameter will contain all previously received chunks of the texture asset starting + from the beginning of the request - - Gets the current balance of the agent + + + Sends the actual request packet to the simulator + + The image to download + Type of the image to download, either a baked + avatar texture or a normal texture + Priority level of the download. Default is + 1,013,000.0f + Number of quality layers to discard. + This controls the end marker of the data sent + Packet number to start the download at. + This controls the start marker of the data sent + Sending a priority of 0 and a discardlevel of -1 aborts + download - - Gets the local ID of the prim the agent is sitting on, - zero if the avatar is not currently sitting + + + Cancel a pending or in process texture request + + The texture assets unique ID - - Gets the of the agents active group. + + + Master Download Thread, Queues up downloads in the threadpool + - - Gets the Agents powers in the currently active group + + + The worker thread that sends the request and handles timeouts + + A object containing the request details - - Current status message for teleporting + + + Handle responses from the simulator that tell us a texture we have requested is unable to be located + or no longer exists. This will remove the request from the pipeline and free up a slot if one is in use + + The sender + The EventArgs object containing the packet data - - Current position of the agent as a relative offset from - the simulator, or the parent object if we are sitting on something + + + Handles the remaining Image data that did not fit in the initial ImageData packet + + The sender + The EventArgs object containing the packet data - - Current rotation of the agent as a relative rotation from - the simulator, or the parent object if we are sitting on something + + + Handle the initial ImageDataPacket sent from the simulator + + The sender + The EventArgs object containing the packet data - - Current position of the agent in the simulator + + Current number of pending and in-process transfers - + - A representing the agents current rotation + A request task containing information and status of a request as it is processed through the - - Returns the global grid position of the avatar + + The current which identifies the current status of the request + + + The Unique Request ID, This is also the Asset ID of the texture being requested + + + The slot this request is occupying in the threadpoolSlots array + + + The ImageType of the request. + + + The callback to fire when the request is complete, will include + the and the + object containing the result data - - - Agent movement and camera control - - Agent movement is controlled by setting specific - After the control flags are set, An AgentUpdate is required to update the simulator of the specified flags - This is most easily accomplished by setting one or more of the AgentMovement properties - - Movement of an avatar is always based on a compass direction, for example AtPos will move the - agent from West to East or forward on the X Axis, AtNeg will of course move agent from - East to West or backward on the X Axis, LeftPos will be South to North or forward on the Y Axis - The Z axis is Up, finer grained control of movements can be done using the Nudge properties - + + If true, indicates the callback will be fired whenever new data is returned from the simulator. + This is used to progressively render textures as portions of the texture are received. - - Agent camera controls + + An object that maintains the data of an request thats in-process. - - Currently only used for hiding your group title + + + + - - Action state of the avatar, which can currently be - typing and editing + + + An instance of DelegateWrapper which calls InvokeWrappedDelegate, + which in turn calls the DynamicInvoke method of the wrapped + delegate + - - + + + Callback used to call EndInvoke on the asynchronously + invoked DelegateWrapper + - - + + + Executes the specified delegate with the specified arguments + asynchronously on a thread pool thread + + + - - + + + Invokes the wrapped delegate synchronously + + + - - + + + Calls EndInvoke on the wrapper and Close on the resulting WaitHandle + to prevent resource leaks + + - - + + + Delegate to wrap another delegate and its arguments + + + - - + + + + - + - + - + - - Timer for sending AgentUpdate packets - - - Default constructor - - + - Send an AgentUpdate with the camera set at the current agent - position and pointing towards the heading specified + Thrown when a packet could not be successfully deserialized - Camera rotation in radians - Whether to send the AgentUpdate reliable - or not - + - Rotates the avatar body and camera toward a target position. - This will also anchor the camera position on the avatar + Default constructor - Region coordinates to turn toward - + - Rotates the avatar body and camera toward a target position. - This will also anchor the camera position on the avatar + Constructor that takes an additional error message - Region coordinates to turn toward - whether to send update or not + An error message to attach to this exception - + - Send new AgentUpdate packet to update our current camera - position and rotation + The header of a message template packet. Holds packet flags, sequence + number, packet ID, and any ACKs that will be appended at the end of + the packet - + - Send new AgentUpdate packet to update our current camera - position and rotation + Convert the AckList to a byte array, used for packet serializing - Whether to require server acknowledgement - of this packet + Reference to the target byte array + Beginning position to start writing to in the byte + array, will be updated with the ending position of the ACK list - + - Send new AgentUpdate packet to update our current camera - position and rotation + - Whether to require server acknowledgement - of this packet - Simulator to send the update to + + + + - + - Builds an AgentUpdate packet entirely from parameters. This - will not touch the state of Self.Movement or - Self.Movement.Camera in any way + - - - - - - - - - - - + + + - + - Sends update of Field of Vision vertical angle to the simulator + A block of data in a packet. Packets are composed of one or more blocks, + each block containing one or more fields - Angle in radians - - Move agent positive along the X axis + + + Create a block from a byte array + + Byte array containing the serialized block + Starting position of the block in the byte array. + This will point to the data after the end of the block when the + call returns - - Move agent negative along the X axis + + + Serialize this block into a byte array + + Byte array to serialize this block into + Starting position in the byte array to serialize to. + This will point to the position directly after the end of the + serialized block when the call returns - - Move agent positive along the Y axis + + Current length of the data in this packet - - Move agent negative along the Y axis + + A generic value, not an actual packet type - - Move agent positive along the Z axis + + - - Move agent negative along the Z axis + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - Causes simulator to make agent fly + + - - Stop movement + + - - Finish animation + + - - Stand up from a sit + + - - Tells simulator to sit agent on ground + + - - Place agent into mouselook mode + + - - Nudge agent positive along the X axis + + - - Nudge agent negative along the X axis + + - - Nudge agent positive along the Y axis + + - - Nudge agent negative along the Y axis + + - - Nudge agent positive along the Z axis + + - - Nudge agent negative along the Z axis + + - - + + - - + + - - Tell simulator to mark agent as away + + - - + + - - + + - - + + - - + + - - - Returns "always run" value, or changes it by sending a SetAlwaysRunPacket - + + - - The current value of the agent control flags + + - - Gets or sets the interval in milliseconds at which - AgentUpdate packets are sent to the current simulator. Setting - this to a non-zero value will also enable the packet sending if - it was previously off, and setting it to zero will disable + + - - Gets or sets whether AgentUpdate packets are sent to - the current simulator + + - - Reset movement controls every time we send an update + + - - - Camera controls for the agent, mostly a thin wrapper around - CoordinateFrame. This class is only responsible for state - tracking and math, it does not send any packets - + + - - + + - - The camera is a local frame of reference inside of - the larger grid space. This is where the math happens + + - - - Default constructor - + + - - + + - - + + - - + + - - + + - - - Used to specify movement actions for your agent - + + - - Empty flag + + - - Move Forward (SL Keybinding: W/Up Arrow) + + - - Move Backward (SL Keybinding: S/Down Arrow) + + - - Move Left (SL Keybinding: Shift-(A/Left Arrow)) + + - - Move Right (SL Keybinding: Shift-(D/Right Arrow)) + + - - Not Flying: Jump/Flying: Move Up (SL Keybinding: E) + + - - Not Flying: Croutch/Flying: Move Down (SL Keybinding: C) + + - - Unused + + - - Unused + + - - Unused + + - - Unused + + - - ORed with AGENT_CONTROL_AT_* if the keyboard is being used + + - - ORed with AGENT_CONTROL_LEFT_* if the keyboard is being used + + - - ORed with AGENT_CONTROL_UP_* if the keyboard is being used + + - - Fly + + - - + + - - Finish our current animation + + - - Stand up from the ground or a prim seat + + - - Sit on the ground at our current location + + - - Whether mouselook is currently enabled + + - - Legacy, used if a key was pressed for less than a certain amount of time + + - - Legacy, used if a key was pressed for less than a certain amount of time + + - - Legacy, used if a key was pressed for less than a certain amount of time + + - - Legacy, used if a key was pressed for less than a certain amount of time + + - - Legacy, used if a key was pressed for less than a certain amount of time + + - - Legacy, used if a key was pressed for less than a certain amount of time + + - - + + - - + + - - Set when the avatar is idled or set to away. Note that the away animation is - activated separately from setting this flag + + - - + + - - + + - - + + - - + + - - - Called once attachment resource usage information has been collected - - Indicates if operation was successfull - Attachment resource usage information + + - - - Represents a single Voice Session to the Vivox service. - + + - - - Close this session. - + + - - - Look up an existing Participants in this session - - - + + - - - Create a Session - Sessions typically represent a connection to a media session with one or more - participants. This is used to generate an ‘outbound’ call to another user or - channel. The specifics depend on the media types involved. A session handle is - required to control the local user functions within the session (or remote - users if the current account has rights to do so). Currently creating a - session automatically connects to the audio media, there is no need to call - Session.Connect at this time, this is reserved for future use. - - Handle returned from successful Connector ‘create’ request - This is the URI of the terminating point of the session (ie who/what is being called) - This is the display name of the entity being called (user or channel) - Only needs to be supplied when the target URI is password protected - This indicates the format of the password as passed in. This can either be - “ClearText” or “SHA1UserName”. If this element does not exist, it is assumed to be “ClearText”. If it is - “SHA1UserName”, the password as passed in is the SHA1 hash of the password and username concatenated together, - then base64 encoded, with the final “=” character stripped off. - - - + + - - - Used to accept a call - - SessionHandle such as received from SessionNewEvent - "default" - + + - - - This command is used to start the audio render process, which will then play - the passed in file through the selected audio render device. This command - should not be issued if the user is on a call. - - The fully qualified path to the sound file. - True if the file is to be played continuously and false if it is should be played once. - + + - - - This command is used to stop the audio render process. - - The fully qualified path to the sound file issued in the start render command. - + + - - - This is used to ‘end’ an established session (i.e. hang-up or disconnect). - - Handle returned from successful Session ‘create’ request or a SessionNewEvent - + + - - - Set the combined speaking and listening position in 3D space. - - Handle returned from successful Session ‘create’ request or a SessionNewEvent - Speaking position - Listening position - + + - - - Set User Volume for a particular user. Does not affect how other users hear that user. - - Handle returned from successful Session ‘create’ request or a SessionNewEvent - - The level of the audio, a number between -100 and 100 where 0 represents ‘normal’ speaking volume - + + - - - Start up the Voice service. - + + - - - Handle miscellaneous request status - - - - ///If something goes wrong, we log it. + + - - - Cleanup oject resources - + + - - - Request voice cap when changing regions - + + - - - Handle a change in session state - + + - - - Close a voice session - - + + - - - Locate a Session context from its handle - - Creates the session context if it does not exist. + + - - - Handle completion of main voice cap request. - - - - + + - - - Daemon has started so connect to it. - + + - - - The daemon TCP connection is open. - + + - - - Handle creation of the Connector. - + + - - - Handle response to audio output device query - + + - - - Handle response to audio input device query - + + - - - Set voice channel for new parcel - - + + - - - Request info from a parcel capability Uri. - - + + - - - Receive parcel voice cap - - - - + + - - - Tell Vivox where we are standing - - This has to be called when we move or turn. + + - - - Start and stop updating out position. - - + + - - - This is used to login a specific user account(s). It may only be called after - Connector initialization has completed successfully - - Handle returned from successful Connector ‘create’ request - User's account name - User's account password - Values may be “AutoAnswer” or “VerifyAnswer” - "" - This is an integer that specifies how often - the daemon will send participant property events while in a channel. If this is not set - the default will be “on state change”, which means that the events will be sent when - the participant starts talking, stops talking, is muted, is unmuted. - The valid values are: - 0 – Never - 5 – 10 times per second - 10 – 5 times per second - 50 – 1 time per second - 100 – on participant state change (this is the default) - false - + + - - - This is used to logout a user session. It should only be called with a valid AccountHandle. - - Handle returned from successful Connector ‘login’ request - + + - - - This is used to initialize and stop the Connector as a whole. The Connector - Create call must be completed successfully before any other requests are made - (typically during application initialization). The shutdown should be called - when the application is shutting down to gracefully release resources - - A string value indicting the Application name - URL for the management server - LoggingSettings - - + + - - - Shutdown Connector -- Should be called when the application is shutting down - to gracefully release resources - - Handle returned from successful Connector ‘create’ request + + - - - Mute or unmute the microphone - - Handle returned from successful Connector ‘create’ request - true (mute) or false (unmute) + + - - - Mute or unmute the speaker - - Handle returned from successful Connector ‘create’ request - true (mute) or false (unmute) + + - - - Set microphone volume - - Handle returned from successful Connector ‘create’ request - The level of the audio, a number between -100 and 100 where - 0 represents ‘normal’ speaking volume + + - - - Set local speaker volume - - Handle returned from successful Connector ‘create’ request - The level of the audio, a number between -100 and 100 where - 0 represents ‘normal’ speaking volume + + - - - This is used to get a list of audio devices that can be used for capture (input) of voice. - - + + - - - This is used to get a list of audio devices that can be used for render (playback) of voice. - + + - - - This command is used to select the render device. - - The name of the device as returned by the Aux.GetRenderDevices command. + + - - - This command is used to select the capture device. - - The name of the device as returned by the Aux.GetCaptureDevices command. + + - - - This command is used to start the audio capture process which will cause - AuxAudioProperty Events to be raised. These events can be used to display a - microphone VU meter for the currently selected capture device. This command - should not be issued if the user is on a call. - - (unused but required) - + + - - - This command is used to stop the audio capture process. - - + + - - - This command is used to set the mic volume while in the audio tuning process. - Once an acceptable mic level is attained, the application must issue a - connector set mic volume command to have that level be used while on voice - calls. - - the microphone volume (-100 to 100 inclusive) - + + - - - This command is used to set the speaker volume while in the audio tuning - process. Once an acceptable speaker level is attained, the application must - issue a connector set speaker volume command to have that level be used while - on voice calls. - - the speaker volume (-100 to 100 inclusive) - + + - - - Starts a thread that keeps the daemon running - - - + + - - - Stops the daemon and the thread keeping it running - + + - - - - - - - + + - - - List of audio input devices - + + - - - List of audio output devices - + + - - - Set audio test mode - + + - - - Event for most mundane request reposnses. - + + - - Response to Connector.Create request + + - - Response to Aux.GetCaptureDevices request + + - - Response to Aux.GetRenderDevices request + + - - Audio Properties Events are sent after audio capture is started. - These events are used to display a microphone VU meter + + - - Response to Account.Login request + + - - This event message is sent whenever the login state of the - particular Account has transitioned from one value to another + + - - Enable logging + + - - The folder where any logs will be created + + - - This will be prepended to beginning of each log file + + - - The suffix or extension to be appended to each log file + + - - - 0: NONE - No logging - 1: ERROR - Log errors only - 2: WARNING - Log errors and warnings - 3: INFO - Log errors, warnings and info - 4: DEBUG - Log errors, warnings, info and debug - + + - - - Constructor for default logging settings - + + - - Audio Properties Events are sent after audio capture is started. These events are used to display a microphone VU meter + + - - - Particle system specific enumerators, flags and methods. - + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - Foliage type for this primitive. Only applicable if this - primitive is foliage + + - - Unknown + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - Identifies the owner if audio or a particle system is - active + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - Objects physics engine propertis + + - - Extra data about primitive + + - - Indicates if prim is attached to an avatar + + - - Number of clients referencing this prim + + - - - Default constructor - + + - - - Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew - parameters in to signed eight bit values - - Floating point parameter to pack - Signed eight bit value containing the packed parameter + + - - - Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew - parameters from signed eight bit integers to floating point values - - Signed eight bit value to unpack - Unpacked floating point value + + - - + + - - + + - - - Current version of the media data for the prim - + + - - - Array of media entries indexed by face number - + + - - + + - - Uses basic heuristics to estimate the primitive shape + + - - - Parameters used to construct a visual representation of a primitive - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - Calculdates hash code for prim construction data - - The has + + - - Attachment point to an avatar + + - - + + - - + + - - + + - - + + - - - Information on the flexible properties of a primitive - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - Default constructor - + + - - - - - - + + - - - - - + + - - - - - + + - - - Information on the light properties of a primitive - + + - - + + - - + + - - + + - - + + - - + + - - - Default constructor - + + - - - - - - + + - - - - - + + - - - - - + + - - - Information on the light properties of a primitive as texture map - + + - - + + - - + + - - - Default constructor - + + - - - - - - + + - - - - - + + - - - - - + + - - - Information on the sculpt properties of a sculpted primitive - + + - - - Default constructor - + + - - - - - - + + - - - Render inside out (inverts the normals). - + + - - - Render an X axis mirror of the sculpty. - + + + + + - - - Extended properties to describe an object - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - Default constructor - + + - - - Set the properties that are set in an ObjectPropertiesFamily packet - - that has - been partially filled by an ObjectPropertiesFamily packet + + - - - Describes physics attributes of the prim - + + - - Primitive's local ID + + - - Density (1000 for normal density) + + - - Friction + + - - Gravity multiplier (1 for normal gravity) + + - - Type of physics representation of this primitive in the simulator + + - - Restitution + + - - - Creates PhysicsProperties from OSD - - OSDMap with incoming data - Deserialized PhysicsProperties object + + - - - Serializes PhysicsProperties to OSD - - OSDMap with serialized PhysicsProperties data + + - - - Texture animation mode - + + - - Disable texture animation + + - - Enable texture animation + + - - Loop when animating textures + + - - Animate in reverse direction + + - - Animate forward then reverse + + - - Slide texture smoothly instead of frame-stepping + + - - Rotate texture instead of using frames + + - - Scale texture instead of using frames + + - - - A single textured face. Don't instantiate this class yourself, use the - methods in TextureEntry - + + - - - Contains the definition for individual faces - - + + - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - In the future this will specify whether a webpage is - attached to this face + + - - + + - - + + - - - Represents all of the texturable faces for an object - - Grid objects have infinite faces, with each face - using the properties of the default face unless set otherwise. So if - you have a TextureEntry with a default texture uuid of X, and face 18 - has a texture UUID of Y, every face would be textured with X except for - face 18 that uses Y. In practice however, primitives utilize a maximum - of nine faces + + - - + + - - + + - - - Constructor that takes a default texture UUID - - Texture UUID to use as the default texture + + - - - Constructor that takes a TextureEntryFace for the - default face - - Face to use as the default face + + - - - Constructor that creates the TextureEntry class from a byte array - - Byte array containing the TextureEntry field - Starting position of the TextureEntry field in - the byte array - Length of the TextureEntry field, in bytes + + - - - This will either create a new face if a custom face for the given - index is not defined, or return the custom face for that index if - it already exists - - The index number of the face to create or - retrieve - A TextureEntryFace containing all the properties for that - face + + - - - - - - + + - - - - - + + - - - - - + + - - - - - + + - - - Controls the texture animation of a particular prim - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - + + - - - - - + + - - - Complete structure for the particle system - + + - - Particle Flags - There appears to be more data packed in to this area - for many particle systems. It doesn't appear to be flag values - and serialization breaks unless there is a flag for every - possible bit so it is left as an unsigned integer + + - - pattern of particles + + - - A representing the maximimum age (in seconds) particle will be displayed - Maximum value is 30 seconds + + - - A representing the number of seconds, - from when the particle source comes into view, - or the particle system's creation, that the object will emits particles; - after this time period no more particles are emitted + + - - A in radians that specifies where particles will not be created + + - - A in radians that specifies where particles will be created + + - - A representing the number of seconds between burts. + + - - A representing the number of meters - around the center of the source where particles will be created. + + - - A representing in seconds, the minimum speed between bursts of new particles - being emitted + + - - A representing in seconds the maximum speed of new particles being emitted. + + - - A representing the maximum number of particles emitted per burst + + - - A which represents the velocity (speed) from the source which particles are emitted + + - - A which represents the Acceleration from the source which particles are emitted + + - - The Key of the texture displayed on the particle + + - - The Key of the specified target object or avatar particles will follow + + - - Flags of particle from + + - - Max Age particle system will emit particles for + + - - The the particle has at the beginning of its lifecycle + + - - The the particle has at the ending of its lifecycle + + - - A that represents the starting X size of the particle - Minimum value is 0, maximum value is 4 + + - - A that represents the starting Y size of the particle - Minimum value is 0, maximum value is 4 + + - - A that represents the ending X size of the particle - Minimum value is 0, maximum value is 4 + + + + + - - A that represents the ending Y size of the particle - Minimum value is 0, maximum value is 4 + + - - A that represents the start glow value - Minimum value is 0, maximum value is 1 + + - - A that represents the end glow value - Minimum value is 0, maximum value is 1 + + - - OpenGL blend function to use at particle source + + - - OpenGL blend function to use at particle destination + + - - - Can this particle system be packed in a legacy compatible way - - True if the particle system doesn't use new particle system features + + - - - Decodes a byte[] array into a ParticleSystem Object - - ParticleSystem object - Start position for BitPacker + + - - - Generate byte[] array from particle data - - Byte array + + - - - Particle source pattern - + + - - None + + - - Drop particles from source position with no force + + - - "Explode" particles in all directions + + - - Particles shoot across a 2D area + + - - Particles shoot across a 3D Cone + + - - Inverse of AngleCone (shoot particles everywhere except the 3D cone defined + + - - - Particle Data Flags - + + - - None + + - - Interpolate color and alpha from start to end + + - - Interpolate scale from start to end + + - - Bounce particles off particle sources Z height + + - - velocity of particles is dampened toward the simulators wind + + - - Particles follow the source + + - - Particles point towards the direction of source's velocity + + - - Target of the particles + + - - Particles are sent in a straight line + + - - Particles emit a glow + + - - used for point/grab/touch + + - - continuous ribbon particle + + - - particle data contains glow + + - - particle data contains blend functions + + - - - Particle Flags Enum - + + - - None + + - - Acceleration and velocity for particles are - relative to the object rotation + + - - Particles use new 'correct' angle parameters + + - - - Return a decoded capabilities message as a strongly typed object - - A string containing the name of the capabilities message key - An to decode - A strongly typed object containing the decoded information from the capabilities message, or null - if no existing Message object exists for the specified event + + - - - Type of gesture step - + + - - - Base class for gesture steps - + + - - - Retururns what kind of gesture step this is - + + - - - Describes animation step of a gesture - + + - - - If true, this step represents start of animation, otherwise animation stop - + + - - - Animation asset - + + - - - Animation inventory name - + + - - - Returns what kind of gesture step this is - + + - - - Describes sound step of a gesture - + + - - - Sound asset - + + - - - Sound inventory name - + + - - - Returns what kind of gesture step this is - + + - - - Describes sound step of a gesture - + + - - - Text to output in chat - + + - - - Returns what kind of gesture step this is - + + - - - Describes sound step of a gesture - + + - - - If true in this step we wait for all animations to finish - + + - - - If true gesture player should wait for the specified amount of time - + + - - - Time in seconds to wait if WaitForAnimation is false - + + - - - Returns what kind of gesture step this is - + + - - - Describes the final step of a gesture - + + - - - Returns what kind of gesture step this is - + + - - - Represents a sequence of animations, sounds, and chat actions - + + - - - Base class for all Asset types - + + - - A byte array containing the raw asset data + + - - True if the asset it only stored on the server temporarily + + - - A unique ID + + - - - Construct a new Asset object - + + - - - Construct a new Asset object - - A unique specific to this asset - A byte array containing the raw asset data + + - - - Regenerates the AssetData byte array from the properties - of the derived class. - + + - - - Decodes the AssetData, placing it in appropriate properties of the derived - class. - - True if the asset decoding succeeded, otherwise false + + - - The assets unique ID + + - - - The "type" of asset, Notecard, Animation, etc - + + - - - Keyboard key that triggers the gestyre - + + - - - Modifier to the trigger key - + + - - - String that triggers playing of the gesture sequence - + + - - - Text that replaces trigger in chat once gesture is triggered - + + - - - Sequence of gesture steps - + + - - - Constructs guesture asset - + + - - - Constructs guesture asset - - A unique specific to this asset - A byte array containing the raw asset data + + - - - Encodes gesture asset suitable for uplaod - + + - - - Decodes gesture assset into play sequence - - true if the asset data was decoded successfully + + - - - Returns asset type - + + - - - Represents an that can be worn on an avatar - such as a Shirt, Pants, etc. - + + - - - Represents a Wearable Asset, Clothing, Hair, Skin, Etc - + + - - A string containing the name of the asset + + - - A string containing a short description of the asset + + - - The Assets WearableType + + - - The For-Sale status of the object + + - - An Integer representing the purchase price of the asset + + - - The of the assets creator + + - - The of the assets current owner + + - - The of the assets prior owner + + - - The of the Group this asset is set to + + - - True if the asset is owned by a + + - - The Permissions mask of the asset + + - - A Dictionary containing Key/Value pairs of the objects parameters + + - - A Dictionary containing Key/Value pairs where the Key is the textures Index and the Value is the Textures + + - - Initializes a new instance of an AssetWearable object + + - - Initializes a new instance of an AssetWearable object with parameters - A unique specific to this asset - A byte array containing the raw asset data + + - - - Decode an assets byte encoded data to a string - - true if the asset data was decoded successfully + + - - - Encode the assets string represantion into a format consumable by the asset server - + + - - Initializes a new instance of an AssetScriptBinary object + + - - Initializes a new instance of an AssetScriptBinary object with parameters - A unique specific to this asset - A byte array containing the raw asset data + + - - Override the base classes AssetType + + - - - Temporary code to produce a tar archive in tar v7 format - + + - - - Binary writer for the underlying stream - + + - - - Write a directory entry to the tar archive. We can only handle one path level right now! - - + + - - - Write a file to the tar archive - - - + + - - - Write a file to the tar archive - - - + + - - - Finish writing the raw tar archive data to a stream. The stream will be closed on completion. - + + - - - Write a particular entry - - - - + + - - - Temporary code to do the bare minimum required to read a tar archive for our purposes - + + - - - Binary reader for the underlying stream - + + - - - Used to trim off null chars - + + - - - Used to trim off space chars - + + - - - Generate a tar reader which reads from the given stream. - - + + - - - Read the next entry in the tar file. - - - - the data for the entry. Returns null if there are no more entries + + - - - Read the next 512 byte chunk of data as a tar header. - - A tar header struct. null if we have reached the end of the archive. + + - - - Read data following a header - - - + + - - - Convert octal bytes to a decimal representation - - - - - + + - - - Static helper functions and global variables - + + - - This header flag signals that ACKs are appended to the packet + + - - This header flag signals that this packet has been sent before + + - - This header flags signals that an ACK is expected for this packet + + - - This header flag signals that the message is compressed using zerocoding + + - - - - - - + + - - - - - - - + + - - - - - - + + - - - - - - - + + - - - Given an X/Y location in absolute (grid-relative) terms, a region - handle is returned along with the local X/Y location in that region - - The absolute X location, a number such as - 255360.35 - The absolute Y location, a number such as - 255360.35 - The sim-local X position of the global X - position, a value from 0.0 to 256.0 - The sim-local Y position of the global Y - position, a value from 0.0 to 256.0 - A 64-bit region handle that can be used to teleport to + + - - - Converts a floating point number to a terse string format used for - transmitting numbers in wearable asset files - - Floating point number to convert to a string - A terse string representation of the input number + + - - - Convert a variable length field (byte array) to a string, with a - field name prepended to each line of the output - - If the byte array has unprintable characters in it, a - hex dump will be written instead - The StringBuilder object to write to - The byte array to convert to a string - A field name to prepend to each line of output + + - - - Decode a zerocoded byte array, used to decompress packets marked - with the zerocoded flag - - Any time a zero is encountered, the next byte is a count - of how many zeroes to expand. One zero is encoded with 0x00 0x01, - two zeroes is 0x00 0x02, three zeroes is 0x00 0x03, etc. The - first four bytes are copied directly to the output buffer. - - The byte array to decode - The length of the byte array to decode. This - would be the length of the packet up to (but not including) any - appended ACKs - The output byte array to decode to - The length of the output buffer + + - - - Encode a byte array with zerocoding. Used to compress packets marked - with the zerocoded flag. Any zeroes in the array are compressed down - to a single zero byte followed by a count of how many zeroes to expand - out. A single zero becomes 0x00 0x01, two zeroes becomes 0x00 0x02, - three zeroes becomes 0x00 0x03, etc. The first four bytes are copied - directly to the output buffer. - - The byte array to encode - The length of the byte array to encode - The output byte array to encode to - The length of the output buffer + + - - - Calculates the CRC (cyclic redundancy check) needed to upload inventory. - - Creation date - Sale type - Inventory type - Type - Asset ID - Group ID - Sale price - Owner ID - Creator ID - Item ID - Folder ID - Everyone mask (permissions) - Flags - Next owner mask (permissions) - Group mask (permissions) - Owner mask (permissions) - The calculated CRC + + - - - Attempts to load a file embedded in the assembly - - The filename of the resource to load - A Stream for the requested file, or null if the resource - was not successfully loaded + + - - - Attempts to load a file either embedded in the assembly or found in - a given search path - - The filename of the resource to load - An optional path that will be searched if - the asset is not found embedded in the assembly - A Stream for the requested file, or null if the resource - was not successfully loaded + + - - - Converts a list of primitives to an object that can be serialized - with the LLSD system - - Primitives to convert to a serializable object - An object that can be serialized with LLSD + + - - - Deserializes OSD in to a list of primitives - - Structure holding the serialized primitive list, - must be of the SDMap type - A list of deserialized primitives + + - - - Converts a struct or class object containing fields only into a key value separated string - - The struct object - A string containing the struct fields as the keys, and the field value as the value separated - - - // Add the following code to any struct or class containing only fields to override the ToString() - // method to display the values of the passed object - - /// Print the struct data as a string - ///A string containing the field name, and field value - public override string ToString() - { - return Helpers.StructToString(this); - } - - + + - - - Passed to Logger.Log() to identify the severity of a log entry - + + - - No logging information will be output + + - - Non-noisy useful information, may be helpful in - debugging a problem + + - - A non-critical error occurred. A warning will not - prevent the rest of the library from operating as usual, - although it may be indicative of an underlying issue + + - - A critical error has occurred. Generally this will - be followed by the network layer shutting down, although the - stability of the library after an error is uncertain + + - - Used for internal testing, this logging level can - generate very noisy (long and/or repetitive) messages. Don't - pass this to the Log() function, use DebugLog() instead. - + + - - - Avatar group management - + + - - Key of Group Member + + - - Total land contribution + + - - Online status information + + - - Abilities that the Group Member has + + - - Current group title + + - - Is a group owner + + - - - Role manager for a group - + + - - Key of the group + + - - Key of Role + + - - Name of Role + + - - Group Title associated with Role + + - - Description of Role + + - - Abilities Associated with Role + + - - Returns the role's title - The role's title + + - - - Class to represent Group Title - + + - - Key of the group + + - - ID of the role title belongs to + + - - Group Title + + - - Whether title is Active + + - - Returns group title + + - - - Represents a group on the grid - + + - - Key of Group + + - - Key of Group Insignia + + - - Key of Group Founder + + - - Key of Group Role for Owners + + - - Name of Group + + - - Text of Group Charter + + - - Title of "everyone" role + + - - Is the group open for enrolement to everyone + + + + + + + + + + + + + + - - Will group show up in search + + - - + + - - + + - - + + - - Is the group Mature + + - - Cost of group membership + + - - + + - - + + - - The total number of current members this group has + + - - The number of roles this group has configured + + - - Show this group in agent's profile + + - - Returns the name of the group - A string containing the name of the group + + - - - A group Vote - + + - - Key of Avatar who created Vote + + - - Text of the Vote proposal + + - - Total number of votes + + - - - A group proposal - + + - - The Text of the proposal + + - - The minimum number of members that must vote before proposal passes or failes + + - - The required ration of yes/no votes required for vote to pass - The three options are Simple Majority, 2/3 Majority, and Unanimous - TODO: this should be an enum + + - - The duration in days votes are accepted + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - Struct representing a group notice - + + - - + + - - + + - - + + - - + + - - - - - + + - - - Struct representing a group notice list entry - + + - - Notice ID + + - - Creation timestamp of notice + + - - Agent name who created notice + + - - Notice subject + + - - Is there an attachment? + + - - Attachment Type + + - - - Struct representing a member of a group chat session and their settings - + + - - The of the Avatar + + - - True if user has voice chat enabled + + - - True of Avatar has moderator abilities + + - - True if a moderator has muted this avatars chat + + - - True if a moderator has muted this avatars voice + + - - - Role update flags - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - Can send invitations to groups default role + + - - Can eject members from group + + - - Can toggle 'Open Enrollment' and change 'Signup fee' + + - - Member is visible in the public member list + + - - Can create new roles + + - - Can delete existing roles + + - - Can change Role names, titles and descriptions + + - - Can assign other members to assigners role + + - - Can assign other members to any role + + - - Can remove members from roles + + - - Can assign and remove abilities in roles + + - - Can change group Charter, Insignia, 'Publish on the web' and which - members are publicly visible in group member listings + + - - Can buy land or deed land to group + + - - Can abandon group owned land to Governor Linden on mainland, or Estate owner for - private estates + + - - Can set land for-sale information on group owned parcels + + - - Can subdivide and join parcels + + - - Can join group chat sessions + + - - Can use voice chat in Group Chat sessions + + - - Can moderate group chat sessions + + - - Can toggle "Show in Find Places" and set search category + + - - Can change parcel name, description, and 'Publish on web' settings + + - - Can set the landing point and teleport routing on group land + + - - Can change music and media settings + + - - Can toggle 'Edit Terrain' option in Land settings + + - - Can toggle various About Land > Options settings + + - - Can always terraform land, even if parcel settings have it turned off + + - - Can always fly while over group owned land + + - - Can always rez objects on group owned land + + - - Can always create landmarks for group owned parcels + + - - Can set home location on any group owned parcel + + - - Can modify public access settings for group owned parcels + + - - Can manager parcel ban lists on group owned land + + - - Can manage pass list sales information + + - - Can eject and freeze other avatars on group owned land + + - - Can return objects set to group + + - - Can return non-group owned/set objects + + - - Can return group owned objects + + - - Can landscape using Linden plants + + - - Can deed objects to group + + - - Can move group owned objects + + - - Can set group owned objects for-sale + + - - Pay group liabilities and receive group dividends + + - - List and Host group events + + - - Can send group notices + + - - Can receive group notices + + - - Can create group proposals + + - - Can vote on group proposals + + - - - Handles all network traffic related to reading and writing group - information - + + - - The event subscribers. null if no subcribers + + - - Raises the CurrentGroups event - A CurrentGroupsEventArgs object containing the - data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + + + + - - Raises the GroupNamesReply event - A GroupNamesEventArgs object containing the - data response from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupProfile event - An GroupProfileEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupMembers event - A GroupMembersEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupRolesDataReply event - A GroupRolesDataReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupRoleMembersReply event - A GroupRolesRoleMembersReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupTitlesReply event - A GroupTitlesReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupAccountSummary event - A GroupAccountSummaryReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupCreated event - An GroupCreatedEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupJoined event - A GroupOperationEventArgs object containing the - result of the operation returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupLeft event - A GroupOperationEventArgs object containing the - result of the operation returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupDropped event - An GroupDroppedEventArgs object containing the - the group your agent left + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupMemberEjected event - An GroupMemberEjectedEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupNoticesListReply event - An GroupNoticesListReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GroupInvitation event - An GroupInvitationEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - A reference to the current instance + + - - Currently-active group members requests + + - - Currently-active group roles requests + + - - Currently-active group role-member requests + + - - Dictionary keeping group members while request is in progress + + - - Dictionary keeping mebmer/role mapping while request is in progress + + - - Dictionary keeping GroupRole information while request is in progress + + - - Caches group name lookups + + - - - Construct a new instance of the GroupManager class - - A reference to the current instance + + - - - Request a current list of groups the avatar is a member of. - - CAPS Event Queue must be running for this to work since the results - come across CAPS. + + - - - Lookup name of group based on groupID - - groupID of group to lookup name for. + + - - - Request lookup of multiple group names - - List of group IDs to request. + + + + + - - Lookup group profile data such as name, enrollment, founder, logo, etc - Subscribe to OnGroupProfile event to receive the results. - group ID (UUID) + + - - Request a list of group members. - Subscribe to OnGroupMembers event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + + - - Request group roles - Subscribe to OnGroupRoles event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + + - - Request members (members,role) role mapping for a group. - Subscribe to OnGroupRolesMembers event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + + - - Request a groups Titles - Subscribe to OnGroupTitles event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + + - - Begin to get the group account summary - Subscribe to the OnGroupAccountSummary event to receive the results. - group ID (UUID) - How long of an interval - Which interval (0 for current, 1 for last) + + - - Invites a user to a group - The group to invite to - A list of roles to invite a person to - Key of person to invite + + - - Set a group as the current active group - group ID (UUID) + + - - Change the role that determines your active title - Group ID to use - Role ID to change to + + - - Set this avatar's tier contribution - Group ID to change tier in - amount of tier to donate + + - - - Save wheather agent wants to accept group notices and list this group in their profile - - Group - Accept notices from this group - List this group in the profile + + - - Request to join a group - Subscribe to OnGroupJoined event for confirmation. - group ID (UUID) to join. + + - - - Request to create a new group. If the group is successfully - created, L$100 will automatically be deducted - - Subscribe to OnGroupCreated event to receive confirmation. - Group struct containing the new group info + + - - Update a group's profile and other information - Groups ID (UUID) to update. - Group struct to update. + + - - Eject a user from a group - Group ID to eject the user from - Avatar's key to eject + + - - Update role information - Modified role to be updated + + - - Create a new group role - Group ID to update - Role to create + + - - Delete a group role - Group ID to update - Role to delete + + - - Remove an avatar from a role - Group ID to update - Role ID to be removed from - Avatar's Key to remove + + - - Assign an avatar to a role - Group ID to update - Role ID to assign to - Avatar's ID to assign to role + + - - Request the group notices list - Group ID to fetch notices for + + - - Request a group notice by key - ID of group notice + + - - Send out a group notice - Group ID to update - GroupNotice structure containing notice data + + - - Start a group proposal (vote) - The Group ID to send proposal to - GroupProposal structure containing the proposal + + - - Request to leave a group - Subscribe to OnGroupLeft event to receive confirmation - The group to leave + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + + + + + + - - Raised when the simulator sends us data containing - our current group membership + + - - Raised when the simulator responds to a RequestGroupName - or RequestGroupNames request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when a response to a RequestGroupAccountSummary is returned - by the simulator + + - - Raised when a request to create a group is successful + + - - Raised when a request to join a group either - fails or succeeds + + - - Raised when a request to leave a group either - fails or succeeds + + - - Raised when A group is removed from the group server + + - - Raised when a request to eject a member from a group either - fails or succeeds + + - - Raised when the simulator sends us group notices - + + - - Raised when another agent invites our avatar to join a group + + - - Contains the current groups your agent is a member of + + - - Construct a new instance of the CurrentGroupsEventArgs class - The current groups your agent is a member of + + - - Get the current groups your agent is a member of + + - - A Dictionary of group names, where the Key is the groups ID and the value is the groups name + + - - Construct a new instance of the GroupNamesEventArgs class - The Group names dictionary + + - - Get the Group Names dictionary + + - - Represents the members of a group + + - - - Construct a new instance of the GroupMembersReplyEventArgs class - - The ID of the request - The ID of the group - The membership list of the group + + - - Get the ID as returned by the request to correlate - this result set and the request + + - - Get the ID of the group + + - - Get the dictionary of members + + - - Represents the roles associated with a group + + - - Construct a new instance of the GroupRolesDataReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The dictionary containing the roles + + - - Get the ID as returned by the request to correlate - this result set and the request + + - - Get the ID of the group + + - - Get the dictionary containing the roles + + - - Represents the Role to Member mappings for a group + + - - Construct a new instance of the GroupRolesMembersReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The member to roles map + + - - Get the ID as returned by the request to correlate - this result set and the request + + - - Get the ID of the group + + - - Get the member to roles map + + - - Represents the titles for a group + + - - Construct a new instance of the GroupTitlesReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The titles + + - - Get the ID as returned by the request to correlate - this result set and the request + + - - Get the ID of the group + + - - Get the titles + + - - Represents the summary data for a group + + - - Construct a new instance of the GroupAccountSummaryReplyEventArgs class - The ID of the group - The summary data + + - - Get the ID of the group + + - - Get the summary data + + - - A response to a group create request + + - - Construct a new instance of the GroupCreatedReplyEventArgs class - The ID of the group - the success or faulure of the request - A string containing additional information + + - - Get the ID of the group + + - - true of the group was created successfully + + - - A string containing the message + + - - Represents a response to a request + + - - Construct a new instance of the GroupOperationEventArgs class - The ID of the group - true of the request was successful + + - - Get the ID of the group + + - - true of the request was successful + + - - Represents your agent leaving a group + + - - Construct a new instance of the GroupDroppedEventArgs class - The ID of the group + + - - Get the ID of the group + + - - Represents a list of active group notices + + - - Construct a new instance of the GroupNoticesListReplyEventArgs class - The ID of the group - The list containing active notices + + - - Get the ID of the group + + - - Get the notices list + + - - Represents the profile of a group + + - - Construct a new instance of the GroupProfileEventArgs class - The group profile + + - - Get the group profile + + - - - Provides notification of a group invitation request sent by another Avatar - - The invitation is raised when another avatar makes an offer for our avatar - to join a group. + + - - The ID of the Avatar sending the group invitation + + - - The name of the Avatar sending the group invitation + + - - A message containing the request information which includes - the name of the group, the groups charter and the fee to join details + + - - The Simulator + + - - Set to true to accept invitation, false to decline + + - - - Abstract base for rendering plugins - + + - - - Generates a basic mesh structure from a primitive - - Primitive to generate the mesh from - Level of detail to generate the mesh at - The generated mesh + + - - - Generates a basic mesh structure from a sculpted primitive and - texture - - Sculpted primitive to generate the mesh from - Sculpt texture - Level of detail to generate the mesh at - The generated mesh + + - - - Generates a series of faces, each face containing a mesh and - metadata - - Primitive to generate the mesh from - Level of detail to generate the mesh at - The generated mesh + + - - - Generates a series of faces for a sculpted prim, each face - containing a mesh and metadata - - Sculpted primitive to generate the mesh from - Sculpt texture - Level of detail to generate the mesh at - The generated mesh + + - - - Apply texture coordinate modifications from a - to a list of vertices - - Vertex list to modify texture coordinates for - Center-point of the face - Face texture parameters - Scale of the prim + + - - - Represents an AssetScriptBinary object containing the - LSO compiled bytecode of an LSL script - + + - - Initializes a new instance of an AssetScriptBinary object + + - - Initializes a new instance of an AssetScriptBinary object with parameters - A unique specific to this asset - A byte array containing the raw asset data + + - - - TODO: Encodes a scripts contents into a LSO Bytecode file - + + - - - TODO: Decode LSO Bytecode into a string - - true + + - - Override the base classes AssetType + + - - - Represents a Landmark with RegionID and Position vector - + + - - UUID of the Landmark target region + + - - Local position of the target + + - - Construct an Asset of type Landmark + + - - - Construct an Asset object of type Landmark - - A unique specific to this asset - A byte array containing the raw asset data + + - - - Encode the raw contents of a string with the specific Landmark format - + + - - - Decode the raw asset data, populating the RegionID and Position - - true if the AssetData was successfully decoded to a UUID and Vector + + - - Override the base classes AssetType + + - - - The current status of a texture request as it moves through the pipeline or final result of a texture request. - + + - - The initial state given to a request. Requests in this state - are waiting for an available slot in the pipeline + + - - A request that has been added to the pipeline and the request packet - has been sent to the simulator + + - - A request that has received one or more packets back from the simulator + + - - A request that has received all packets back from the simulator + + - - A request that has taken longer than - to download OR the initial packet containing the packet information was never received + + - - The texture request was aborted by request of the agent + + - - The simulator replied to the request that it was not able to find the requested texture + + - - - A callback fired to indicate the status or final state of the requested texture. For progressive - downloads this will fire each time new asset data is returned from the simulator. - - The indicating either Progress for textures not fully downloaded, - or the final result of the request after it has been processed through the TexturePipeline - The object containing the Assets ID, raw data - and other information. For progressive rendering the will contain - the data from the beginning of the file. For failed, aborted and timed out requests it will contain - an empty byte array. + + - - - Texture request download handler, allows a configurable number of download slots which manage multiple - concurrent texture downloads from the - - This class makes full use of the internal - system for full texture downloads. + + - - A dictionary containing all pending and in-process transfer requests where the Key is both the RequestID - and also the Asset Texture ID, and the value is an object containing the current state of the request and also - the asset data as it is being re-assembled + + - - Holds the reference to the client object + + - - Maximum concurrent texture requests allowed at a time + + - - An array of objects used to manage worker request threads + + - - An array of worker slots which shows the availablity status of the slot + + - - The primary thread which manages the requests. + + - - true if the TexturePipeline is currently running + + - - A synchronization object used by the primary thread + + - - A refresh timer used to increase the priority of stalled requests + + - - - Default constructor, Instantiates a new copy of the TexturePipeline class - - Reference to the instantiated object + + - - - Initialize callbacks required for the TexturePipeline to operate - + + - - - Shutdown the TexturePipeline and cleanup any callbacks or transfers - + + - - - Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - A float indicating the requested priority for the transfer. Higher priority values tell the simulator - to prioritize the request before lower valued requests. An image already being transferred using the can have - its priority changed by resending the request with the new priority value - Number of quality layers to discard. - This controls the end marker of the data sent - The packet number to begin the request at. A value of 0 begins the request - from the start of the asset texture - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request + + - - - Sends the actual request packet to the simulator - - The image to download - Type of the image to download, either a baked - avatar texture or a normal texture - Priority level of the download. Default is - 1,013,000.0f - Number of quality layers to discard. - This controls the end marker of the data sent - Packet number to start the download at. - This controls the start marker of the data sent - Sending a priority of 0 and a discardlevel of -1 aborts - download + + - - - Cancel a pending or in process texture request - - The texture assets unique ID + + - - - Master Download Thread, Queues up downloads in the threadpool - + + - - - The worker thread that sends the request and handles timeouts - - A object containing the request details + + - - - Handle responses from the simulator that tell us a texture we have requested is unable to be located - or no longer exists. This will remove the request from the pipeline and free up a slot if one is in use - - The sender - The EventArgs object containing the packet data + + - - - Handles the remaining Image data that did not fit in the initial ImageData packet - - The sender - The EventArgs object containing the packet data + + - - - Handle the initial ImageDataPacket sent from the simulator - - The sender - The EventArgs object containing the packet data + + - - Current number of pending and in-process transfers + + - - - A request task containing information and status of a request as it is processed through the - + + - - The current which identifies the current status of the request + + - - The Unique Request ID, This is also the Asset ID of the texture being requested + + - - The slot this request is occupying in the threadpoolSlots array + + - - The ImageType of the request. + + - - The callback to fire when the request is complete, will include - the and the - object containing the result data + + - - If true, indicates the callback will be fired whenever new data is returned from the simulator. - This is used to progressively render textures as portions of the texture are received. + + - - An object that maintains the data of an request thats in-process. + + - - - A set of textures that are layered on texture of each other and "baked" - in to a single texture, for avatar appearances - + + - - Final baked texture + + - - Component layers + + - - Width of the final baked image and scratchpad + + - - Height of the final baked image and scratchpad + + - - Bake type + + - - - Default constructor - - Bake type + + - - - Adds layer for baking - - TexturaData struct that contains texture and its params + + - - - Converts avatar texture index (face) to Bake type - - Face number (AvatarTextureIndex) - BakeType, layer to which this texture belongs to + + - - - Make sure images exist, resize source if needed to match the destination - - Destination image - Source image - Sanitization was succefull + + + + + + + + + + + - - - Fills a baked layer as a solid *appearing* color. The colors are - subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from - compressing it too far since it seems to cause upload failures if - the image is a pure solid color - - Color of the base of this layer + + - - - Fills a baked layer as a solid *appearing* color. The colors are - subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from - compressing it too far since it seems to cause upload failures if - the image is a pure solid color - - Red value - Green value - Blue value + + - - Final baked texture + + - - Component layers + + - - Width of the final baked image and scratchpad + + - - Height of the final baked image and scratchpad + + - - Bake type + + - - Is this one of the 3 skin bakes + + - - - Represents a Sound Asset - + + - - Initializes a new instance of an AssetSound object + + - - Initializes a new instance of an AssetSound object with parameters - A unique specific to this asset - A byte array containing the raw asset data + + - - - TODO: Encodes a sound file - + + - - - TODO: Decode a sound file - - true + + - - Override the base classes AssetType + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - - - + + - - - The ObservableDictionary class is used for storing key/value pairs. It has methods for firing - events to subscribers when items are added, removed, or changed. - - Key - Value + + - - - A dictionary of callbacks to fire when specified action occurs - + + - - - Register a callback to be fired when an action occurs - - The action - The callback to fire + + - - - Unregister a callback - - The action - The callback to fire + + - - - - - - + + - - Internal dictionary that this class wraps around. Do not - modify or enumerate the contents of this dictionary without locking + + - - - Initializes a new instance of the Class - with the specified key/value, has the default initial capacity. - - - - // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value. - public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(); - - + + - - - Initializes a new instance of the Class - with the specified key/value, With its initial capacity specified. - - Initial size of dictionary - - - // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value, - // initially allocated room for 10 entries. - public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(10); - - + + - - - Try to get entry from the with specified key - - Key to use for lookup - Value returned - if specified key exists, if not found - - - // find your avatar using the Simulator.ObjectsAvatars ObservableDictionary: - Avatar av; - if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) - Console.WriteLine("Found Avatar {0}", av.Name); - - - + + - - - Finds the specified match. - - The match. - Matched value - - - // use a delegate to find a prim in the ObjectsPrimitives ObservableDictionary - // with the ID 95683496 - uint findID = 95683496; - Primitive findPrim = sim.ObjectsPrimitives.Find( - delegate(Primitive prim) { return prim.ID == findID; }); - - + + - - Find All items in an - return matching items. - a containing found items. - - Find All prims within 20 meters and store them in a List - - int radius = 20; - List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( - delegate(Primitive prim) { - Vector3 pos = prim.Position; - return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); - } - ); - - + + - - Find All items in an - return matching keys. - a containing found keys. - - Find All keys which also exist in another dictionary - - List<UUID> matches = myDict.FindAll( - delegate(UUID id) { - return myOtherDict.ContainsKey(id); - } - ); - - + + + + + - - Check if Key exists in Dictionary - Key to check for - if found, otherwise + + - - Check if Value exists in Dictionary - Value to check for - if found, otherwise + + - - - Adds the specified key to the dictionary, dictionary locking is not performed, - - - The key - The value + + - - - Removes the specified key, dictionary locking is not performed - - The key. - if successful, otherwise + + - - - Clear the contents of the dictionary - + + - - - Enumerator for iterating dictionary entries - - + + - - - Gets the number of Key/Value pairs contained in the - + + - - - Indexer for the dictionary - - The key - The value + + - - - A Name Value pair with additional settings, used in the protocol - primarily to transmit avatar names and active group in object packets - + + - - + + - - + + - - + + - - + + - - + + - - - Constructor that takes all the fields as parameters - - - - - - + + - - - Constructor that takes a single line from a NameValue field - - + + - - Type of the value + + - - Unknown + + - - String value + + - - + + - - + + - - + + - - + + - - Deprecated + + - - String value, but designated as an asset + + - - + + - - - - + + - - + + - - + + - - + + - - + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - - Wrapper around a byte array that allows bit to be packed and unpacked - one at a time or by a variable amount. Useful for very tightly packed - data like LayerData packets - + + - - + + - - - Default constructor, initialize the bit packer / bit unpacker - with a byte array and starting position - - Byte array to pack bits in to or unpack from - Starting position in the byte array + + - - - Pack a floating point value in to the data - - Floating point value to pack + + - - - Pack part or all of an integer in to the data - - Integer containing the data to pack - Number of bits of the integer to pack + + - - - Pack part or all of an unsigned integer in to the data - - Unsigned integer containing the data to pack - Number of bits of the integer to pack + + - - - Pack a single bit in to the data - - Bit to pack + + - - - - - - - - + + + + + + + + - - - - - + + - - - - - + + - - - Unpacking a floating point value from the data - - Unpacked floating point value + + - - - Unpack a variable number of bits from the data in to integer format - - Number of bits to unpack - An integer containing the unpacked bits - This function is only useful up to 32 bits + + - - - Unpack a variable number of bits from the data in to unsigned - integer format - - Number of bits to unpack - An unsigned integer containing the unpacked bits - This function is only useful up to 32 bits + + - - - Unpack a 16-bit signed integer - - 16-bit signed integer + + - - - Unpack a 16-bit unsigned integer - - 16-bit unsigned integer + + - - - Unpack a 32-bit signed integer - - 32-bit signed integer + + - - - Unpack a 32-bit unsigned integer - - 32-bit unsigned integer + + - - + + - - + + - - - Index of TextureEntry slots for avatar appearances - + + - - - Bake layers for avatar appearance - + + - - - Appearance Flags, introdued with server side baking, currently unused - + + - - Maximum number of concurrent downloads for wearable assets and textures + + - - Maximum number of concurrent uploads for baked textures + + - - Timeout for fetching inventory listings + + - - Timeout for fetching a single wearable, or receiving a single packet response + + - - Timeout for fetching a single texture + + - - Timeout for uploading a single baked texture + + - - Number of times to retry bake upload + + - - When changing outfit, kick off rebake after - 20 seconds has passed since the last change + + - - Total number of wearables for each avatar + + - - Total number of baked textures on each avatar + + - - Total number of wearables per bake layer + + - - Mask for multiple attachments + + - - Mapping between BakeType and AvatarTextureIndex + + - - Map of what wearables are included in each bake + + - - Magic values to finalize the cache check hashes for each - bake + + - - Default avatar texture, used to detect when a custom - texture is not set for a face + + - - The event subscribers. null if no subcribers + + - - Raises the AgentWearablesReply event - An AgentWearablesReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the CachedBakesReply event - An AgentCachedBakesReplyEventArgs object containing the - data returned from the data server AgentCachedTextureResponse + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the AppearanceSet event - An AppearanceSetEventArgs object indicating if the operatin was successfull + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the RebakeAvatarRequested event - An RebakeAvatarTexturesEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - Visual parameters last sent to the sim + + - - Textures about this client sent to the sim + + - - A cache of wearables currently being worn + + - - A cache of textures currently being worn + + - - Incrementing serial number for AgentCachedTexture packets + + - - Incrementing serial number for AgentSetAppearance packets + + - - Indicates if WearablesRequest succeeded + + - - Indicates whether or not the appearance thread is currently - running, to prevent multiple appearance threads from running - simultaneously + + + + + + + + - - Reference to our agent + + - - - Timer used for delaying rebake on changing outfit - + + - - - Main appearance thread - + + - - - Is server baking complete. It needs doing only once - + + - - - Default constructor - - A reference to our agent + + - - - Obsolete method for setting appearance. This function no longer does anything. - Use RequestSetAppearance() to manually start the appearance thread - + + - - - Obsolete method for setting appearance. This function no longer does anything. - Use RequestSetAppearance() to manually start the appearance thread - - Unused parameter + + - - - Starts the appearance setting thread - + + - - - Starts the appearance setting thread - - True to force rebaking, otherwise false + + - - - Check if current region supports server side baking - - True if server side baking support is detected + + - - - Ask the server what textures our agent is currently wearing - + + - - - Build hashes out of the texture assetIDs for each baking layer to - ask the simulator whether it has cached copies of each baked texture - + + - - - Returns the AssetID of the asset that is currently being worn in a - given WearableType slot - - WearableType slot to get the AssetID for - The UUID of the asset being worn in the given slot, or - UUID.Zero if no wearable is attached to the given slot or wearables - have not been downloaded yet + + - - - Add a wearable to the current outfit and set appearance - - Wearable to be added to the outfit + + - - - Add a wearable to the current outfit and set appearance - - Wearable to be added to the outfit - Should existing item on the same point or of the same type be replaced + + - - - Add a list of wearables to the current outfit and set appearance - - List of wearable inventory items to - be added to the outfit - Should existing item on the same point or of the same type be replaced + + - - - Add a list of wearables to the current outfit and set appearance - - List of wearable inventory items to - be added to the outfit - Should existing item on the same point or of the same type be replaced + + - - - Remove a wearable from the current outfit and set appearance - - Wearable to be removed from the outfit + + - - - Removes a list of wearables from the current outfit and set appearance - - List of wearable inventory items to - be removed from the outfit + + - - - Replace the current outfit with a list of wearables and set appearance - - List of wearable inventory items that - define a new outfit + + - - - Replace the current outfit with a list of wearables and set appearance - - List of wearable inventory items that - define a new outfit - Check if we have all body parts, set this to false only - if you know what you're doing + + - - - Checks if an inventory item is currently being worn - - The inventory item to check against the agent - wearables - The WearableType slot that the item is being worn in, - or WearbleType.Invalid if it is not currently being worn + + - - - Returns a copy of the agents currently worn wearables - - A copy of the agents currently worn wearables - Avoid calling this function multiple times as it will make - a copy of all of the wearable data each time + + - - - Calls either or - depending on the value of - replaceItems - - List of wearable inventory items to add - to the outfit or become a new outfit - True to replace existing items with the - new list of items, false to add these items to the existing outfit + + - - - Adds a list of attachments to our agent - - A List containing the attachments to add - If true, tells simulator to remove existing attachment - first + + - - - Adds a list of attachments to our agent - - A List containing the attachments to add - If true, tells simulator to remove existing attachment - If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments) - first + + - - - Attach an item to our agent at a specific attach point - - A to attach - the on the avatar - to attach the item to + + - - - Attach an item to our agent at a specific attach point - - A to attach - the on the avatar - If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments) - to attach the item to + + - - - Attach an item to our agent specifying attachment details - - The of the item to attach - The attachments owner - The name of the attachment - The description of the attahment - The to apply when attached - The of the attachment - The on the agent - to attach the item to + + - - - Attach an item to our agent specifying attachment details - - The of the item to attach - The attachments owner - The name of the attachment - The description of the attahment - The to apply when attached - The of the attachment - The on the agent - If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments) - to attach the item to + + + + + - - - Detach an item from our agent using an object - - An object + + - - - Detach an item from our agent - - The inventory itemID of the item to detach + + - - - Inform the sim which wearables are part of our current outfit - + + - - - Replaces the Wearables collection with a list of new wearable items - - Wearable items to replace the Wearables collection with + + - - - Calculates base color/tint for a specific wearable - based on its params - - All the color info gathered from wearable's VisualParams - passed as list of ColorParamInfo tuples - Base color/tint for the wearable + + - - - Blocking method to populate the Wearables dictionary - - True on success, otherwise false + + - - - Blocking method to populate the Textures array with cached bakes - - True on success, otherwise false + + - - - Populates textures and visual params from a decoded asset - - Wearable to decode - - Populates textures and visual params from a decoded asset - - Wearable to decode + + - - - Blocking method to download and parse currently worn wearable assets - - True on success, otherwise false + + - - - Get a list of all of the textures that need to be downloaded for a - single bake layer - - Bake layer to get texture AssetIDs for - A list of texture AssetIDs to download + + - - - Helper method to lookup the TextureID for a single layer and add it - to a list if it is not already present - - - + + - - - Blocking method to download all of the textures needed for baking - the given bake layers - - A list of layers that need baking - No return value is given because the baking will happen - whether or not all textures are successfully downloaded + + - - - Blocking method to create and upload baked textures for all of the - missing bakes - - True on success, otherwise false + + - - - Blocking method to create and upload a baked texture for a single - bake layer - - Layer to bake - True on success, otherwise false + + - - - Blocking method to upload a baked texture - - Five channel JPEG2000 texture data to upload - UUID of the newly created asset on success, otherwise UUID.Zero + + - - - Creates a dictionary of visual param values from the downloaded wearables - - A dictionary of visual param indices mapping to visual param - values for our agent that can be fed to the Baker class + + - - - Initate server baking process - - True if the server baking was successful + + - - - Get the latest version of COF - - Current Outfit Folder (or null if getting the data failed) + + - - - Create an AgentSetAppearance packet from Wearables data and the - Textures array and send it - + + - - - Converts a WearableType to a bodypart or clothing WearableType - - A WearableType - AssetType.Bodypart or AssetType.Clothing or AssetType.Unknown + + - - - Converts a BakeType to the corresponding baked texture slot in AvatarTextureIndex - - A BakeType - The AvatarTextureIndex slot that holds the given BakeType + + - - - Gives the layer number that is used for morph mask - - >A BakeType - Which layer number as defined in BakeTypeToTextures is used for morph mask + + - - - Converts a BakeType to a list of the texture slots that make up that bake - - A BakeType - A list of texture slots that are inputs for the given bake + + - - Triggered when an AgentWearablesUpdate packet is received, - telling us what our avatar is currently wearing - request. + + - - Raised when an AgentCachedTextureResponse packet is - received, giving a list of cached bakes that were found on the - simulator - request. + + - - - Raised when appearance data is sent to the simulator, also indicates - the main appearance thread is finished. - - request. + + - - - Triggered when the simulator requests the agent rebake its appearance. - - + + - - - Returns true if AppearanceManager is busy and trying to set or change appearance will fail - + + - - - Contains information about a wearable inventory item - + + - - Inventory ItemID of the wearable + + - - AssetID of the wearable asset + + - - WearableType of the wearable + + - - AssetType of the wearable + + - - Asset data for the wearable + + - - - Data collected from visual params for each wearable - needed for the calculation of the color - + + - - - Holds a texture assetID and the data needed to bake this layer into - an outfit texture. Used to keep track of currently worn textures - and baking data - + + - - A texture AssetID + + - - Asset data for the texture + + - - Collection of alpha masks that needs applying + + - - Tint that should be applied to the texture + + - - Where on avatar does this texture belong + + - - Contains the Event data returned from the data server from an AgentWearablesRequest + + - - Construct a new instance of the AgentWearablesReplyEventArgs class + + - - Contains the Event data returned from the data server from an AgentCachedTextureResponse + + - - Construct a new instance of the AgentCachedBakesReplyEventArgs class + + - - Contains the Event data returned from an AppearanceSetRequest + + - - - Triggered when appearance data is sent to the sim and - the main appearance thread is done. - Indicates whether appearance setting was successful + + - - Indicates whether appearance setting was successful + + - - Contains the Event data returned from the data server from an RebakeAvatarTextures + + - - - Triggered when the simulator sends a request for this agent to rebake - its appearance - - The ID of the Texture Layer to bake + + - - The ID of the Texture Layer to bake + + - - - - + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + - - Information about agents display name + + - - Agent UUID + + - - Username + + - - Display name + + - - First name (legacy) + + - - Last name (legacy) + + - - Is display name default display name + + - - Cache display name until + + - - Last updated timestamp + + - - - Creates AgentDisplayName object from OSD - - Incoming OSD data - AgentDisplayName object + + - - - Return object as OSD map - - OSD containing agent's display name data + + - - Full name (legacy) + + - - - Holds group information for Avatars such as those you might find in a profile - + + - - true of Avatar accepts group notices + + - - Groups Key + + - - Texture Key for groups insignia + + - - Name of the group + + - - Powers avatar has in the group + + - - Avatars Currently selected title + + - - true of Avatar has chosen to list this in their profile + + - - - Contains an animation currently being played by an agent - + + - - The ID of the animation asset + + - - A number to indicate start order of currently playing animations - On Linden Grids this number is unique per region, with OpenSim it is per client + + - - + + - + + + + - Holds group information on an individual profile pick + Operation to apply when applying color to texture - + - Retrieve friend status notifications, and retrieve avatar names and - profiles + Information needed to translate visual param value to RGBA color - - The event subscribers, null of no subscribers - - - Raises the AvatarAnimation Event - An AvatarAnimationEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - The event subscribers, null of no subscribers - - - Raises the AvatarAppearance Event - A AvatarAppearanceEventArgs object containing - the data sent from the simulator - - - Thread sync lock object + + + Construct VisualColorParam + + Operation to apply when applying color to texture + Colors - - The event subscribers, null of no subscribers + + + Represents alpha blending and bump infor for a visual parameter + such as sleive length + - - Raises the UUIDNameReply Event - A UUIDNameReplyEventArgs object containing - the data sent from the simulator + + Stregth of the alpha to apply - - Thread sync lock object + + File containing the alpha channel - - The event subscribers, null of no subscribers + + Skip blending if parameter value is 0 - - Raises the AvatarInterestsReply Event - A AvatarInterestsReplyEventArgs object containing - the data sent from the simulator + + Use miltiply insted of alpha blending - - Thread sync lock object + + + Create new alhpa information for a visual param + + Stregth of the alpha to apply + File containing the alpha channel + Skip blending if parameter value is 0 + Use miltiply insted of alpha blending - - The event subscribers, null of no subscribers + + + A single visual characteristic of an avatar mesh, such as eyebrow height + - - Raises the AvatarPropertiesReply Event - A AvatarPropertiesReplyEventArgs object containing - the data sent from the simulator + + Index of this visual param - - Thread sync lock object + + Internal name - - The event subscribers, null of no subscribers + + Group ID this parameter belongs to - - Raises the AvatarGroupsReply Event - A AvatarGroupsReplyEventArgs object containing - the data sent from the simulator + + Name of the wearable this parameter belongs to - - Thread sync lock object + + Displayable label of this characteristic - - The event subscribers, null of no subscribers + + Displayable label for the minimum value of this characteristic - - Raises the AvatarPickerReply Event - A AvatarPickerReplyEventArgs object containing - the data sent from the simulator + + Displayable label for the maximum value of this characteristic - - Thread sync lock object + + Default value - - The event subscribers, null of no subscribers + + Minimum value - - Raises the ViewerEffectPointAt Event - A ViewerEffectPointAtEventArgs object containing - the data sent from the simulator + + Maximum value - - Thread sync lock object + + Is this param used for creation of bump layer? - - The event subscribers, null of no subscribers + + Alpha blending/bump info - - Raises the ViewerEffectLookAt Event - A ViewerEffectLookAtEventArgs object containing - the data sent from the simulator + + Color information - - Thread sync lock object + + Array of param IDs that are drivers for this parameter - - The event subscribers, null of no subscribers + + + Set all the values through the constructor + + Index of this visual param + Internal name + + + Displayable label of this characteristic + Displayable label for the minimum value of this characteristic + Displayable label for the maximum value of this characteristic + Default value + Minimum value + Maximum value + Is this param used for creation of bump layer? + Array of param IDs that are drivers for this parameter + Alpha blending/bump info + Color information - - Raises the ViewerEffect Event - A ViewerEffectEventArgs object containing - the data sent from the simulator + + + Holds the Params array of all the avatar appearance parameters + - - Thread sync lock object + + + Base class for all Asset types + - - The event subscribers, null of no subscribers + + A byte array containing the raw asset data - - Raises the AvatarPicksReply Event - A AvatarPicksReplyEventArgs object containing - the data sent from the simulator + + True if the asset it only stored on the server temporarily - - Thread sync lock object + + A unique ID - - The event subscribers, null of no subscribers + + + Construct a new Asset object + - - Raises the PickInfoReply Event - A PickInfoReplyEventArgs object containing - the data sent from the simulator + + + Construct a new Asset object + + A unique specific to this asset + A byte array containing the raw asset data - - Thread sync lock object + + + Regenerates the AssetData byte array from the properties + of the derived class. + - - The event subscribers, null of no subscribers + + + Decodes the AssetData, placing it in appropriate properties of the derived + class. + + True if the asset decoding succeeded, otherwise false - - Raises the AvatarClassifiedReply Event - A AvatarClassifiedReplyEventArgs object containing - the data sent from the simulator + + The assets unique ID - - Thread sync lock object + + + The "type" of asset, Notecard, Animation, etc + - - The event subscribers, null of no subscribers + + + Constants for the archiving module + - - Raises the ClassifiedInfoReply Event - A ClassifiedInfoReplyEventArgs object containing - the data sent from the simulator + + + Path for region settings. + - - Thread sync lock object + + + The location of the archive control file + - - The event subscribers, null of no subscribers + + + Path for the assets held in an archive + - - Raises the DisplayNameUpdate Event - A DisplayNameUpdateEventArgs object containing - the data sent from the simulator + + + Path for the prims file + - - Thread sync lock object + + + Path for terrains. Technically these may be assets, but I think it's quite nice to split them out. + - + - Represents other avatars + Path for region settings. - - - Tracks the specified avatar on your map - Avatar ID to track + + + The character the separates the uuid from extension information in an archived asset filename + - + - Request a single avatar name + Extensions used for asset types in the archive - The avatar key to retrieve a name for - + - Request a list of avatar names + Archives assets - The avatar keys to retrieve names for - + - Check if Display Names functionality is available + Archive assets - True if Display name functionality is available - + - Request retrieval of display names (max 90 names per request) + Archive the assets given to this archiver to the given archive. - List of UUIDs to lookup - Callback to report result of the operation + - + - Start a request for Avatar Properties + Write an assets metadata file to the given archive - + - + - Search for an avatar (first name, last name) + Write asset data files to the given archive - The name to search for - An ID to associate with this query + - + - Start a request for Avatar Picks + Temporary code to do the bare minimum required to read a tar archive for our purposes - UUID of the avatar - + - Start a request for Avatar Classifieds + Binary reader for the underlying stream - UUID of the avatar - + - Start a request for details of a specific profile pick + Used to trim off null chars - UUID of the avatar - UUID of the profile pick - + - Start a request for details of a specific profile classified + Used to trim off space chars - UUID of the avatar - UUID of the profile classified - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - + - EQ Message fired when someone nearby changes their display name + Generate a tar reader which reads from the given stream. - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet + - + - Crossed region handler for message that comes across the EventQueue. Sent to an agent - when the agent crosses a sim border into a new region. + Read the next entry in the tar file. - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Raised when the simulator sends us data containing - an agents animation playlist - - - Raised when the simulator sends us data containing - the appearance information for an agent - - - Raised when the simulator sends us data containing - agent names/id values - - - Raised when the simulator sends us data containing - the interests listed in an agents profile - - - Raised when the simulator sends us data containing - profile property information for an agent - - - Raised when the simulator sends us data containing - the group membership an agent is a member of - - - Raised when the simulator sends us data containing - name/id pair - - - Raised when the simulator sends us data containing - the objects and effect when an agent is pointing at - - - Raised when the simulator sends us data containing - the objects and effect when an agent is looking at - - - Raised when the simulator sends us data containing - an agents viewer effect information - - - Raised when the simulator sends us data containing - the top picks from an agents profile - - - Raised when the simulator sends us data containing - the Pick details - - - Raised when the simulator sends us data containing - the classified ads an agent has placed + + + the data for the entry. Returns null if there are no more entries - - Raised when the simulator sends us data containing - the details of a classified ad + + + Read the next 512 byte chunk of data as a tar header. + + A tar header struct. null if we have reached the end of the archive. - - Raised when the simulator sends us data containing - the details of display name change + + + Read data following a header + + + - + - Callback giving results when fetching display names + Convert octal bytes to a decimal representation - If the request was successful - Array of display names - Array of UUIDs that could not be fetched + + + + - - Provides data for the event - The event occurs when the simulator sends - the animation playlist for an agent - - The following code example uses the and - properties to display the animation playlist of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAnimation += Avatars_AvatarAnimation; - - private void Avatars_AvatarAnimation(object sender, AvatarAnimationEventArgs e) - { - // create a dictionary of "known" animations from the Animations class using System.Reflection - Dictionary<UUID, string> systemAnimations = new Dictionary<UUID, string>(); - Type type = typeof(Animations); - System.Reflection.FieldInfo[] fields = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); - foreach (System.Reflection.FieldInfo field in fields) - { - systemAnimations.Add((UUID)field.GetValue(type), field.Name); - } - - // find out which animations being played are known animations and which are assets - foreach (Animation animation in e.Animations) - { - if (systemAnimations.ContainsKey(animation.AnimationID)) - { - Console.WriteLine("{0} is playing {1} ({2}) sequence {3}", e.AvatarID, - systemAnimations[animation.AnimationID], animation.AnimationSequence); - } - else - { - Console.WriteLine("{0} is playing {1} (Asset) sequence {2}", e.AvatarID, - animation.AnimationID, animation.AnimationSequence); - } - } - } - - + + + Temporary code to produce a tar archive in tar v7 format + - + - Construct a new instance of the AvatarAnimationEventArgs class + Binary writer for the underlying stream - The ID of the agent - The list of animations to start - - Get the ID of the agent + + + Write a directory entry to the tar archive. We can only handle one path level right now! + + - - Get the list of animations to start + + + Write a file to the tar archive + + + - - Provides data for the event - The event occurs when the simulator sends - the appearance data for an avatar - - The following code example uses the and - properties to display the selected shape of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; - - // handle the data when the event is raised - void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) - { - Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") - } - - + + + Write a file to the tar archive + + + - + - Construct a new instance of the AvatarAppearanceEventArgs class + Finish writing the raw tar archive data to a stream. The stream will be closed on completion. - The simulator request was from - The ID of the agent - true of the agent is a trial account - The default agent texture - The agents appearance layer textures - The for the agent - - Get the Simulator this request is from of the agent + + + Write a particular entry + + + + - - Get the ID of the agent + + + Represents an Animation + - - true if the agent is a trial account + + Default Constructor - - Get the default agent texture + + + Construct an Asset object of type Animation + + A unique specific to this asset + A byte array containing the raw asset data - - Get the agents appearance layer textures + + Override the base classes AssetType - - Get the for the agent + + + Represents an that represents an avatars body ie: Hair, Etc. + - - Version of the appearance system used. - Value greater than 0 indicates that server side baking is used + + + Represents a Wearable Asset, Clothing, Hair, Skin, Etc + - - Version of the Current Outfit Folder the appearance is based on + + A string containing the name of the asset - - Appearance flags, introduced with server side baking, currently unused + + A string containing a short description of the asset - - Represents the interests from the profile of an agent + + The Assets WearableType - - Get the ID of the agent + + The For-Sale status of the object - - The properties of an agent + + An Integer representing the purchase price of the asset - - Get the ID of the agent + + The of the assets creator - - Get the ID of the agent + + The of the assets current owner - - Get the ID of the agent + + The of the assets prior owner - - Get the ID of the avatar + + The of the Group this asset is set to - - - Event args class for display name notification messages - + + True if the asset is owned by a - - - Capability to load TGAs to Bitmap - + + The Permissions mask of the asset - + + A Dictionary containing Key/Value pairs of the objects parameters + + + A Dictionary containing Key/Value pairs where the Key is the textures Index and the Value is the Textures + + + Initializes a new instance of an AssetWearable object + + + Initializes a new instance of an AssetWearable object with parameters + A unique specific to this asset + A byte array containing the raw asset data + + - Represents Mesh asset + Decode an assets byte encoded data to a string + true if the asset data was decoded successfully - + - Decoded mesh data + Encode the assets string represantion into a format consumable by the asset server - - Initializes a new instance of an AssetMesh object + + Initializes a new instance of an AssetBodyPart object - - Initializes a new instance of an AssetMesh object with parameters + + Initializes a new instance of an AssetBodyPart object with parameters A unique specific to this asset A byte array containing the raw asset data - + + Override the base classes AssetType + + - TODO: Encodes Collada file into LLMesh format + Represents a Callingcard with AvatarID and Position vector - + + UUID of the Callingcard target avatar + + + Construct an Asset of type Callingcard + + - Decodes mesh asset. See - to furter decode it for rendering - true + Construct an Asset object of type Callingcard + + A unique specific to this asset + A byte array containing the raw asset data - - Override the base classes AssetType + + + Constuct an asset of type Callingcard + + UUID of the target avatar - + - NetworkManager is responsible for managing the network layer of - OpenMetaverse. It tracks all the server connections, serializes - outgoing traffic and deserializes incoming traffic, and provides - instances of delegates for network-related events. + Encode the raw contents of a string with the specific Callingcard format + + - Login Routines + Decode the raw asset data, populating the AvatarID and Position + true if the AssetData was successfully decoded to a UUID and Vector - - The event subscribers, null of no subscribers + + Override the base classes AssetType - - Raises the PacketSent Event - A PacketSentEventArgs object containing - the data sent from the simulator + + + Represents an that can be worn on an avatar + such as a Shirt, Pants, etc. + - - Thread sync lock object + + Initializes a new instance of an AssetScriptBinary object - - The event subscribers, null of no subscribers + + Initializes a new instance of an AssetScriptBinary object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - Raises the LoggedOut Event - A LoggedOutEventArgs object containing - the data sent from the simulator + + Override the base classes AssetType - - Thread sync lock object + + + Type of gesture step + + + + + Base class for gesture steps + - - The event subscribers, null of no subscribers + + + Retururns what kind of gesture step this is + - - Raises the SimConnecting Event - A SimConnectingEventArgs object containing - the data sent from the simulator + + + Describes animation step of a gesture + - - Thread sync lock object + + + If true, this step represents start of animation, otherwise animation stop + - - The event subscribers, null of no subscribers + + + Animation asset + - - Raises the SimConnected Event - A SimConnectedEventArgs object containing - the data sent from the simulator + + + Animation inventory name + - - Thread sync lock object + + + Returns what kind of gesture step this is + - - The event subscribers, null of no subscribers + + + Describes sound step of a gesture + - - Raises the SimDisconnected Event - A SimDisconnectedEventArgs object containing - the data sent from the simulator + + + Sound asset + - - Thread sync lock object + + + Sound inventory name + - - The event subscribers, null of no subscribers + + + Returns what kind of gesture step this is + - - Raises the Disconnected Event - A DisconnectedEventArgs object containing - the data sent from the simulator + + + Describes sound step of a gesture + - - Thread sync lock object + + + Text to output in chat + - - The event subscribers, null of no subscribers + + + Returns what kind of gesture step this is + - - Raises the SimChanged Event - A SimChangedEventArgs object containing - the data sent from the simulator + + + Describes sound step of a gesture + - - Thread sync lock object + + + If true in this step we wait for all animations to finish + - - The event subscribers, null of no subscribers + + + If true gesture player should wait for the specified amount of time + - - Raises the EventQueueRunning Event - A EventQueueRunningEventArgs object containing - the data sent from the simulator + + + Time in seconds to wait if WaitForAnimation is false + - - Thread sync lock object + + + Returns what kind of gesture step this is + - - All of the simulators we are currently connected to + + + Describes the final step of a gesture + - - Handlers for incoming capability events + + + Returns what kind of gesture step this is + - - Handlers for incoming packets + + + Represents a sequence of animations, sounds, and chat actions + - - Incoming packets that are awaiting handling + + + Keyboard key that triggers the gestyre + - - Outgoing packets that are awaiting handling + + + Modifier to the trigger key + - + - Default constructor + String that triggers playing of the gesture sequence - Reference to the GridClient object - + - Register an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library + Text that replaces trigger in chat once gesture is triggered - Packet type to trigger events for - Callback to fire when a packet of this type - is received - + - Register an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library + Sequence of gesture steps - Packet type to trigger events for - Callback to fire when a packet of this type - is received - True if the callback should be ran - asynchronously. Only set this to false (synchronous for callbacks - that will always complete quickly) - If any callback for a packet type is marked as - asynchronous, all callbacks for that packet type will be fired - asynchronously - + - Unregister an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library + Constructs guesture asset - Packet type this callback is registered with - Callback to stop firing events for - + - Register a CAPS event handler. This is a low level event interface - and should only be used if you are doing something not supported in - the library + Constructs guesture asset - Name of the CAPS event to register a handler for - Callback to fire when a CAPS event is received + A unique specific to this asset + A byte array containing the raw asset data - + - Unregister a CAPS event handler. This is a low level event interface - and should only be used if you are doing something not supported in - the library + Encodes gesture asset suitable for uplaod - Name of the CAPS event this callback is - registered with - Callback to stop firing events for - + - Send a packet to the simulator the avatar is currently occupying + Decodes gesture assset into play sequence - Packet to send + true if the asset data was decoded successfully - + - Send a packet to a specified simulator + Returns asset type - Packet to send - Simulator to send the packet to - + - Connect to a simulator + Represents a Landmark with RegionID and Position vector - IP address to connect to - Port to connect to - Handle for this simulator, to identify its - location in the grid - Whether to set CurrentSim to this new - connection, use this if the avatar is moving in to this simulator - URL of the capabilities server to use for - this sim connection - A Simulator object on success, otherwise null - + + UUID of the Landmark target region + + + Local position of the target + + + Construct an Asset of type Landmark + + - Connect to a simulator + Construct an Asset object of type Landmark - IP address and port to connect to - Handle for this simulator, to identify its - location in the grid - Whether to set CurrentSim to this new - connection, use this if the avatar is moving in to this simulator - URL of the capabilities server to use for - this sim connection - A Simulator object on success, otherwise null + A unique specific to this asset + A byte array containing the raw asset data - + - Initiate a blocking logout request. This will return when the logout - handshake has completed or when Settings.LOGOUT_TIMEOUT - has expired and the network layer is manually shut down + Encode the raw contents of a string with the specific Landmark format - + - Initiate the logout process. Check if logout succeeded with the - OnLogoutReply event, and if this does not fire the - Shutdown() function needs to be manually called + Decode the raw asset data, populating the RegionID and Position + true if the AssetData was successfully decoded to a UUID and Vector - + + Override the base classes AssetType + + - Close a connection to the given simulator + Represents Mesh asset - - - + - Shutdown will disconnect all the sims except for the current sim - first, and then kill the connection to CurrentSim. This should only - be called if the logout process times out on RequestLogout + Decoded mesh data - Type of shutdown - + + Initializes a new instance of an AssetMesh object + + + Initializes a new instance of an AssetMesh object with parameters + A unique specific to this asset + A byte array containing the raw asset data + + - Shutdown will disconnect all the sims except for the current sim - first, and then kill the connection to CurrentSim. This should only - be called if the logout process times out on RequestLogout + TODO: Encodes Collada file into LLMesh format - Type of shutdown - Shutdown message - + - Searches through the list of currently connected simulators to find - one attached to the given IPEndPoint + Decodes mesh asset. See + to furter decode it for rendering + true + + + Override the base classes AssetType + + + + Represents an Animation - IPEndPoint of the Simulator to search for - A Simulator reference on success, otherwise null - + + Default Constructor + + - Fire an event when an event queue connects for capabilities + Construct an Asset object of type Animation - Simulator the event queue is attached to + Asset type + A unique specific to this asset + A byte array containing the raw asset data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Override the base classes AssetType - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Represents a string of characters encoded with specific formatting properties + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + A text string containing main text of the notecard - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + List of s embedded on the notecard - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Construct an Asset of type Notecard - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Construct an Asset object of type Notecard + + A unique specific to this asset + A byte array containing the raw asset data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Encode the raw contents of a string with the specific Linden Text properties + - - The event subscribers, null of no subscribers + + + Decode the raw asset data including the Linden Text properties + + true if the AssetData was successfully decoded - - Raises the LoginProgress Event - A LoginProgressEventArgs object containing - the data sent from the simulator + + Override the base classes AssetType - - Thread sync lock object + + + A linkset asset, containing a parent primitive and zero or more children + - - Seed CAPS URL returned from the login server + + Initializes a new instance of an AssetPrim object - - Maximum number of groups an agent can belong to, -1 for unlimited + + + Initializes a new instance of an AssetPrim object + + A unique specific to this asset + A byte array containing the raw asset data - - Server side baking service URL + + + + - - A list of packets obtained during the login process which - networkmanager will log but not process + + + + + - + + Override the base classes AssetType + + - Generate sane default values for a login request + Only used internally for XML serialization/deserialization - Account first name - Account last name - Account password - Client application name (channel) - Client application name + version - A populated struct containing - sane defaults - + - Simplified login that takes the most common and required fields + The deserialized form of a single primitive in a linkset asset - Account first name - Account last name - Account password - Client application name (channel) - Client application name + version - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error - + - Simplified login that takes the most common fields along with a - starting location URI, and can accept an MD5 string instead of a - plaintext password + Represents an AssetScriptBinary object containing the + LSO compiled bytecode of an LSL script - Account first name - Account last name - Account password or MD5 hash of the password - such as $1$1682a1e45e9f957dcdf0bb56eb43319c - Client application name (channel) - Starting location URI that can be built with - StartLocation() - Client application name + version - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error - + + Initializes a new instance of an AssetScriptBinary object + + + Initializes a new instance of an AssetScriptBinary object with parameters + A unique specific to this asset + A byte array containing the raw asset data + + - Login that takes a struct of all the values that will be passed to - the login server + TODO: Encodes a scripts contents into a LSO Bytecode file - The values that will be passed to the login - server, all fields must be set even if they are String.Empty - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error - + - Build a start location URI for passing to the Login function + TODO: Decode LSO Bytecode into a string - Name of the simulator to start in - X coordinate to start at - Y coordinate to start at - Z coordinate to start at - String with a URI that can be used to login to a specified - location + true - + + Override the base classes AssetType + + - LoginParams and the initial login XmlRpcRequest were made on a remote machine. - This method now initializes libomv with the results. + Represents an LSL Text object containing a string of UTF encoded characters - + + A string of characters represting the script contents + + + Initializes a new AssetScriptText object + + - Handles response from XML-RPC login replies + Initializes a new AssetScriptText object with parameters + A unique specific to this asset + A byte array containing the raw asset data - + - Handles response from XML-RPC login replies with already parsed LoginResponseData + Encode a string containing the scripts contents into byte encoded AssetData - + - Handle response from LLSD login replies + Decode a byte array containing the scripts contents into a string - - - + true if decoding is successful - - - Get current OS - - Either "Win" or "Linux" + + Override the base classes AssetType - + - Get clients default Mac Address + Represents a Sound Asset - A string containing the first found Mac Address - - Raised when the simulator sends us data containing - ... + + Initializes a new instance of an AssetSound object - - Raised when the simulator sends us data containing - ... + + Initializes a new instance of an AssetSound object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - Raised when the simulator sends us data containing - ... + + + TODO: Encodes a sound file + - - Raised when the simulator sends us data containing - ... + + + TODO: Decode a sound file + + true - - Raised when the simulator sends us data containing - ... + + Override the base classes AssetType - - Raised when the simulator sends us data containing - ... + + + Represents a texture + - - Raised when the simulator sends us data containing - ... + + A object containing image data - - Raised when the simulator sends us data containing - ... + + - - Unique identifier associated with our connections to - simulators + + - - The simulator that the logged in avatar is currently - occupying + + Initializes a new instance of an AssetTexture object - - Shows whether the network layer is logged in to the - grid or not + + + Initializes a new instance of an AssetTexture object + + A unique specific to this asset + A byte array containing the raw asset data - - Number of packets in the incoming queue + + + Initializes a new instance of an AssetTexture object + + A object containing texture data - - Number of packets in the outgoing queue + + + Populates the byte array with a JPEG2000 + encoded image created from the data in + - - Raised when the simulator sends us data containing - ... + + + Decodes the JPEG2000 data in AssetData to the + object + + True if the decoding was successful, otherwise false - - Called when a reply is received from the login server, the - login sequence will block until this event returns + + + Decodes the begin and end byte positions for each quality layer in + the image + + - - Current state of logging in + + Override the base classes AssetType - - Upon login failure, contains a short string key for the - type of login error that occurred + + = - - The raw XML-RPC reply from the login server, exactly as it - was received (minus the HTTP header) + + Number of times we've received an unknown CAPS exception in series. - - During login this contains a descriptive version of - LoginStatusCode. After a successful login this will contain the - message of the day, and after a failed login a descriptive error - message will be returned + + For exponential backoff on error. - + - Explains why a simulator or the grid disconnected from us + A set of textures that are layered on texture of each other and "baked" + in to a single texture, for avatar appearances - - The client requested the logout or simulator disconnect + + Final baked texture - - The server notified us that it is disconnecting + + Component layers - - Either a socket was closed or network traffic timed out + + Width of the final baked image and scratchpad - - The last active simulator shut down + + Height of the final baked image and scratchpad - + + Bake type + + - Holds a simulator reference and a decoded packet, these structs are put in - the packet inbox for event handling + Default constructor + Bake type - - Reference to the simulator that this packet came from - - - Packet that needs to be processed - - + - Holds a simulator reference and a serialized packet, these structs are put in - the packet outbox for sending + Adds layer for baking + TexturaData struct that contains texture and its params - - Reference to the simulator this packet is destined for - - - Packet that needs to be sent - - - Sequence number of the wrapped packet - - - Number of times this packet has been resent - - - Environment.TickCount when this packet was last sent over the wire - - - Type of the packet - - + - + Converts avatar texture index (face) to Bake type - - - - - + Face number (AvatarTextureIndex) + BakeType, layer to which this texture belongs to - + - Map layer request type + Make sure images exist, resize source if needed to match the destination + Destination image + Source image + Sanitization was succefull - - Objects and terrain are shown - - - Only the terrain is shown, no objects - - - Overlay showing land for sale and for auction - - + - Type of grid item, such as telehub, event, populator location, etc. + Fills a baked layer as a solid *appearing* color. The colors are + subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from + compressing it too far since it seems to cause upload failures if + the image is a pure solid color + Color of the base of this layer - - Telehub - - - PG rated event - - - Mature rated event + + + Fills a baked layer as a solid *appearing* color. The colors are + subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from + compressing it too far since it seems to cause upload failures if + the image is a pure solid color + + Red value + Green value + Blue value - - Popular location + + Final baked texture - - Locations of avatar groups in a region + + Component layers - - Land for sale + + Width of the final baked image and scratchpad - - Classified ad + + Height of the final baked image and scratchpad - - Adult rated event + + Bake type - - Adult land for sale + + Is this one of the 3 skin bakes - + - Information about a region on the grid map + Image width - - Sim X position on World Map - - - Sim Y position on World Map + + + Image height + - - Sim Name (NOTE: In lowercase!) + + + Image channel flags + - - + + + Red channel data + - - Appears to always be zero (None) + + + Green channel data + - - Sim's defined Water Height + + + Blue channel data + - - + + + Alpha channel data + - - UUID of the World Map image + + + Bump channel data + - - Unique identifier for this region, a combination of the X - and Y position + + + Create a new blank image + + width + height + channel flags - + - + - + - + Convert the channels in the image. Channels are created or destroyed as required. - + new channel flags - + - + Resize or stretch the image using nearest neighbor (ugly) resampling - - + new width + new height - + - Visual chunk of the grid map + Create a byte array containing 32-bit RGBA data with a bottom-left + origin, suitable for feeding directly into OpenGL + A byte array containing raw texture data - + - Base class for Map Items + Create a byte array containing 32-bit RGBA data with a bottom-left + origin, suitable for feeding directly into OpenGL + A byte array containing raw texture data - - The Global X position of the item + + + A Wrapper around openjpeg to encode and decode images to and from byte arrays + - - The Global Y position of the item + + TGA Header size - - Get the Local X position of the item + + OpenJPEG is not threadsafe, so this object is used to lock + during calls into unmanaged code - - Get the Local Y position of the item + + + Encode a object into a byte array + + The object to encode + true to enable lossless conversion, only useful for small images ie: sculptmaps + A byte array containing the encoded Image object - - Get the Handle of the region + + + Encode a object into a byte array + + The object to encode + a byte array of the encoded image - + - Represents an agent or group of agents location + Decode JPEG2000 data to an and + + JPEG2000 encoded data + ManagedImage object to decode to + Image object to decode to + True if the decode succeeds, otherwise false - + - Represents a Telehub location + + + + - + - Represents a non-adult parcel of land for sale + + + + + - + - Represents an Adult parcel of land for sale + Encode a object into a byte array + The source object to encode + true to enable lossless decoding + A byte array containing the source Bitmap object - + - Represents a PG Event + Defines the beginning and ending file positions of a layer in an + LRCP-progression JPEG2000 file - + - Represents a Mature event + This structure is used to marshal both encoded and decoded images. + MUST MATCH THE STRUCT IN dotnet.h! - + - Represents an Adult event + Information about a single packet in a JPEG2000 stream - + + Packet start position + + + Packet header end position + + + Packet end position + + - Manages grid-wide tasks such as the world map + Capability to load TGAs to Bitmap - - The event subscribers. null if no subcribers + + - - Raises the CoarseLocationUpdate event - A CoarseLocationUpdateEventArgs object containing the - data sent by simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GridRegion event - A GridRegionEventArgs object containing the - data sent by simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GridLayer event - A GridLayerEventArgs object containing the - data sent by simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the GridItems event - A GridItemEventArgs object containing the - data sent by simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - Raises the RegionHandleReply event - A RegionHandleReplyEventArgs object containing the - data sent by simulator + + - - Thread sync lock object + + - - A dictionary of all the regions, indexed by region name + + - - A dictionary of all the regions, indexed by region handle + + - - - Constructor - - Instance of GridClient object to associate with this GridManager instance + + - - - - - + + - - - Request a map layer - - The name of the region - The type of layer + + - - - - - - - - - - + + - - - - - - - - - + + - - - - - - - + + - - - Request data for all mainland (Linden managed) simulators - + + - - - Request the region handle for the specified region UUID - - UUID of the region to look up + + - - - Get grid region information using the region name, this function - will block until it can find the region or gives up - - Name of sim you're looking for - Layer that you are requesting - Will contain a GridRegion for the sim you're - looking for if successful, otherwise an empty structure - True if the GridRegion was successfully fetched, otherwise - false + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Raised when the simulator sends a - containing the location of agents in the simulator + + - - Raised when the simulator sends a Region Data in response to - a Map request + + - - Raised when the simulator sends GridLayer object containing - a map tile coordinates and texture information + + - - Raised when the simulator sends GridItems object containing - details on events, land sales at a specific location + + - - Raised in response to a Region lookup + + - - Unknown + + - - Current direction of the sun + + - - Current angular velocity of the sun + + - - Microseconds since the start of SL 4-hour day + + - - = + + - - Number of times we've received an unknown CAPS exception in series. + + - - For exponential backoff on error. + + - - X position of this patch + + - - Y position of this patch + + - - A 16x16 array of floats holding decompressed layer data + + - - - Creates a LayerData packet for compressed land data given a full - simulator heightmap and an array of indices of patches to compress - - A 256 * 256 array of floating point values - specifying the height at each meter in the simulator - Array of indexes in the 16x16 grid of patches - for this simulator. For example if 1 and 17 are specified, patches - x=1,y=0 and x=1,y=1 are sent - + + - - - Add a patch of terrain to a BitPacker - - BitPacker to write the patch to - Heightmap of the simulator, must be a 256 * - 256 float array - X offset of the patch to create, valid values are - from 0 to 15 - Y offset of the patch to create, valid values are - from 0 to 15 + + - - - Add a custom decoder callback - - The key of the field to decode - The custom decode handler + + - - - Remove a custom decoder callback - - The key of the field to decode - The custom decode handler + + - - - Creates a formatted string containing the values of a Packet - - The Packet - A formatted string of values of the nested items in the Packet object + + - - - Decode an IMessage object into a beautifully formatted string - - The IMessage object - Recursion level (used for indenting) - A formatted string containing the names and values of the source object + + - - - A custom decoder callback - - The key of the object - the data to decode - A string represending the fieldData + + - - - Singleton logging class for the entire library - + + - - log4net logging engine + + - - - Default constructor - + + - - - Send a log message to the logging engine - - The log message - The severity of the log entry + + - - - Send a log message to the logging engine - - The log message - The severity of the log entry - Instance of the client + + - - - Send a log message to the logging engine - - The log message - The severity of the log entry - Exception that was raised + + - - - Send a log message to the logging engine - - The log message - The severity of the log entry - Instance of the client - Exception that was raised + + - - - If the library is compiled with DEBUG defined, an event will be - fired if an OnLogMessage handler is registered and the - message will be sent to the logging engine - - The message to log at the DEBUG level to the - current logging engine + + - - - If the library is compiled with DEBUG defined and - GridClient.Settings.DEBUG is true, an event will be - fired if an OnLogMessage handler is registered and the - message will be sent to the logging engine - - The message to log at the DEBUG level to the - current logging engine - Instance of the client + + - - Triggered whenever a message is logged. If this is left - null, log messages will go to the console + + - - - Callback used for client apps to receive log messages from - the library - - Data being logged - The severity of the log entry from + + - - Sort by name + + - - Sort by date + + - - Sort folders by name, regardless of whether items are - sorted by name or date + + - - Place system folders at the top + + + + + - - - Possible destinations for DeRezObject request - + + - - + + - - Copy from in-world to agent inventory + + - - Derez to TaskInventory + + - - + + - - Take Object + + - - + + - - Delete Object + + - - Put an avatar attachment into agent inventory + + - - + + - - Return an object back to the owner's inventory + + - - Return a deeded object back to the last owner's inventory + + - - - Upper half of the Flags field for inventory items - + + - - Indicates that the NextOwner permission will be set to the - most restrictive set of permissions found in the object set - (including linkset items and object inventory items) on next rez + + - - Indicates that the object sale information has been - changed + + - - If set, and a slam bit is set, indicates BaseMask will be overwritten on Rez + + - - If set, and a slam bit is set, indicates OwnerMask will be overwritten on Rez + + - - If set, and a slam bit is set, indicates GroupMask will be overwritten on Rez + + - - If set, and a slam bit is set, indicates EveryoneMask will be overwritten on Rez + + - - If set, and a slam bit is set, indicates NextOwnerMask will be overwritten on Rez + + - - Indicates whether this object is composed of multiple - items or not + + - - Indicates that the asset is only referenced by this - inventory item. If this item is deleted or updated to reference a - new assetID, the asset can be deleted + + - - - Base Class for Inventory Items - + + - - of item/folder + + - - of parent folder + + - - Name of item/folder + + - - Item/Folder Owners + + - - - Constructor, takes an itemID as a parameter - - The of the item + + - - - - - + + - - - - - + + - - - Generates a number corresponding to the value of the object to support the use of a hash table, - suitable for use in hashing algorithms and data structures such as a hash table - - A Hashcode of all the combined InventoryBase fields + + - - - Determine whether the specified object is equal to the current object - - InventoryBase object to compare against - true if objects are the same + + - - - Determine whether the specified object is equal to the current object - - InventoryBase object to compare against - true if objects are the same + + - - - Convert inventory to OSD - - OSD representation + + - - - An Item in Inventory - + + - - The of this item + + - - The combined of this item + + - - The type of item from + + - - The type of item from the enum + + - - The of the creator of this item + + - - A Description of this item + + - - The s this item is set to or owned by + + - - If true, item is owned by a group + + - - The price this item can be purchased for + + - - The type of sale from the enum + + - - Combined flags from + + - - Time and date this inventory item was created, stored as - UTC (Coordinated Universal Time) + + - - Used to update the AssetID in requests sent to the server + + - - The of the previous owner of the item + + - - - Construct a new InventoryItem object - - The of the item + + - - - Construct a new InventoryItem object of a specific Type - - The type of item from - of the item + + - - - Indicates inventory item is a link - - True if inventory item is a link to another inventory item + + - - - - - + + - - - - - + + - - - Generates a number corresponding to the value of the object to support the use of a hash table. - Suitable for use in hashing algorithms and data structures such as a hash table - - A Hashcode of all the combined InventoryItem fields + + - - - Compares an object - - The object to compare - true if comparison object matches + + - - - Determine whether the specified object is equal to the current object - - The object to compare against - true if objects are the same + + - - - Determine whether the specified object is equal to the current object - - The object to compare against - true if objects are the same + + - - - Create InventoryItem from OSD - - OSD Data that makes up InventoryItem - Inventory item created + + - - - Convert InventoryItem to OSD - - OSD representation of InventoryItem + + - - - InventoryTexture Class representing a graphical image - - + + - - - Construct an InventoryTexture object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryTexture object from a serialization stream - + + - - - InventorySound Class representing a playable sound - + + - - - Construct an InventorySound object - - A which becomes the - objects AssetUUID + + - - - Construct an InventorySound object from a serialization stream - + + - - - InventoryCallingCard Class, contains information on another avatar - + + - - - Construct an InventoryCallingCard object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryCallingCard object from a serialization stream - + + - - - InventoryLandmark Class, contains details on a specific location - + + - - - Construct an InventoryLandmark object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryLandmark object from a serialization stream - + + + + + - - - Landmarks use the InventoryItemFlags struct and will have a flag of 1 set if they have been visited - + + - - - InventoryObject Class contains details on a primitive or coalesced set of primitives - + + - - - Construct an InventoryObject object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryObject object from a serialization stream - + + - - - Gets or sets the upper byte of the Flags value - + + - - - Gets or sets the object attachment point, the lower byte of the Flags value - + + - - - InventoryNotecard Class, contains details on an encoded text document - + + - - - Construct an InventoryNotecard object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryNotecard object from a serialization stream - + + - - - InventoryCategory Class - - TODO: Is this even used for anything? + + - - - Construct an InventoryCategory object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryCategory object from a serialization stream - + + - - - InventoryLSL Class, represents a Linden Scripting Language object - + + - - - Construct an InventoryLSL object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryLSL object from a serialization stream - + + - - - InventorySnapshot Class, an image taken with the viewer - + + - - - Construct an InventorySnapshot object - - A which becomes the - objects AssetUUID + + - - - Construct an InventorySnapshot object from a serialization stream - + + - - - InventoryAttachment Class, contains details on an attachable object - + + - - - Construct an InventoryAttachment object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryAttachment object from a serialization stream - + + - - - Get the last AttachmentPoint this object was attached to - + + - - - InventoryWearable Class, details on a clothing item or body part - + + - - - Construct an InventoryWearable object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryWearable object from a serialization stream - + + - - - The , Skin, Shape, Skirt, Etc - + + - - - InventoryAnimation Class, A bvh encoded object which animates an avatar - + + - - - Construct an InventoryAnimation object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryAnimation object from a serialization stream - + + - - - InventoryGesture Class, details on a series of animations, sounds, and actions - + + - - - Construct an InventoryGesture object - - A which becomes the - objects AssetUUID + + - - - Construct an InventoryGesture object from a serialization stream - + + - - - A folder contains s and has certain attributes specific - to itself - + + - - The Preferred for a folder. + + - - The Version of this folder + + - - Number of child items this folder contains. + + - - - Constructor - - UUID of the folder + + - - - - - + + - - - Get Serilization data for this InventoryFolder object - + + - - - Construct an InventoryFolder object from a serialization stream - + + - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - Create InventoryFolder from OSD - - OSD Data that makes up InventoryFolder - Inventory folder created + + - - - Convert InventoryItem to OSD - - OSD representation of InventoryItem + + - - - Tools for dealing with agents inventory - + + - - Used for converting shadow_id to asset_id + + - - The event subscribers, null of no subscribers + + - - Raises the ItemReceived Event - A ItemReceivedEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the FolderUpdated Event - A FolderUpdatedEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the InventoryObjectOffered Event - A InventoryObjectOfferedEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the TaskItemReceived Event - A TaskItemReceivedEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the FindObjectByPath Event - A FindObjectByPathEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the TaskInventoryReply Event - A TaskInventoryReplyEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the SaveAssetToInventory Event - A SaveAssetToInventoryEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the ScriptRunningReply Event - A ScriptRunningReplyEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - Partial mapping of AssetTypes to folder names + + - - - Default constructor - - Reference to the GridClient object + + - - - Fetch an inventory item from the dataserver - - The items - The item Owners - a integer representing the number of milliseconds to wait for results - An object on success, or null if no item was found - Items will also be sent to the event + + - - - Request A single inventory item - - The items - The item Owners - + + - - - Request inventory items - - Inventory items to request - Owners of the inventory items - + + - - - Request inventory items via Capabilities - - Inventory items to request - Owners of the inventory items - + + - - - Get contents of a folder - - The of the folder to search - The of the folders owner - true to retrieve folders - true to retrieve items - sort order to return results in - a integer representing the number of milliseconds to wait for results - A list of inventory items matching search criteria within folder - - InventoryFolder.DescendentCount will only be accurate if both folders and items are - requested + + - - - Request the contents of an inventory folder - - The folder to search - The folder owners - true to return s contained in folder - true to return s containd in folder - the sort order to return items in - + + - - - Request the contents of an inventory folder using HTTP capabilities - - The folder to search - The folder owners - true to return s contained in folder - true to return s containd in folder - the sort order to return items in - + + - - - Returns the UUID of the folder (category) that defaults to - containing 'type'. The folder is not necessarily only for that - type - - This will return the root folder if one does not exist - - The UUID of the desired folder if found, the UUID of the RootFolder - if not found, or UUID.Zero on failure + + - - - Find an object in inventory using a specific path to search - - The folder to begin the search in - The object owners - A string path to search - milliseconds to wait for a reply - Found items or if - timeout occurs or item is not found + + - - - Find inventory items by path - - The folder to begin the search in - The object owners - A string path to search, folders/objects separated by a '/' - Results are sent to the event + + - - - Search inventory Store object for an item or folder - - The folder to begin the search in - An array which creates a path to search - Number of levels below baseFolder to conduct searches - if True, will stop searching after first match is found - A list of inventory items found + + - - - Move an inventory item or folder to a new location - - The item or folder to move - The to move item or folder to + + - - - Move an inventory item or folder to a new location and change its name - - The item or folder to move - The to move item or folder to - The name to change the item or folder to + + - - - Move and rename a folder - - The source folders - The destination folders - The name to change the folder to + + - - - Update folder properties - - of the folder to update - Sets folder's parent to - Folder name - Folder type + + - - - Move a folder - - The source folders - The destination folders + + - - - Move multiple folders, the keys in the Dictionary parameter, - to a new parents, the value of that folder's key. - - A Dictionary containing the - of the source as the key, and the - of the destination as the value + + - - - Move an inventory item to a new folder - - The of the source item to move - The of the destination folder + + - - - Move and rename an inventory item - - The of the source item to move - The of the destination folder - The name to change the folder to + + - - - Move multiple inventory items to new locations - - A Dictionary containing the - of the source item as the key, and the - of the destination folder as the value + + - - - Remove descendants of a folder - - The of the folder + + - - - Remove a single item from inventory - - The of the inventory item to remove + + - - - Remove a folder from inventory - - The of the folder to remove + + - - - Remove multiple items or folders from inventory - - A List containing the s of items to remove - A List containing the s of the folders to remove + + - - - Empty the Lost and Found folder - + + - - - Empty the Trash folder - + + - - - - - - - - - Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. - - - + + - - - - - - - - - Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. - - - - + + - - - Creates a new inventory folder - - ID of the folder to put this folder in - Name of the folder to create - The UUID of the newly created folder + + + + + - - - Creates a new inventory folder - - ID of the folder to put this folder in - Name of the folder to create - Sets this folder as the default folder - for new assets of the specified type. Use AssetType.Unknown - to create a normal folder, otherwise it will likely create a - duplicate of an existing folder type - The UUID of the newly created folder - If you specify a preferred type of AsseType.Folder - it will create a new root folder which may likely cause all sorts - of strange problems + + - - - Create an inventory item and upload asset data - - Asset data - Inventory item name - Inventory item description - Asset type - Inventory type - Put newly created inventory in this folder - Delegate that will receive feedback on success or failure + + - - - Create an inventory item and upload asset data - - Asset data - Inventory item name - Inventory item description - Asset type - Inventory type - Put newly created inventory in this folder - Permission of the newly created item - (EveryoneMask, GroupMask, and NextOwnerMask of Permissions struct are supported) - Delegate that will receive feedback on success or failure + + - - - Creates inventory link to another inventory item or folder - - Put newly created link in folder with this UUID - Inventory item or folder - Method to call upon creation of the link + + - - - Creates inventory link to another inventory item - - Put newly created link in folder with this UUID - Original inventory item - Method to call upon creation of the link + + - - - Creates inventory link to another inventory folder - - Put newly created link in folder with this UUID - Original inventory folder - Method to call upon creation of the link + + - - - Creates inventory link to another inventory item or folder - - Put newly created link in folder with this UUID - Original item's UUID - Name - Description - Asset Type - Inventory Type - Transaction UUID - Method to call upon creation of the link + + - - - - - - - - + + - - - - - - - - - + + - - - - - - - - - + + - - - Request a copy of an asset embedded within a notecard - - Usually UUID.Zero for copying an asset from a notecard - UUID of the notecard to request an asset from - Target folder for asset to go to in your inventory - UUID of the embedded asset - callback to run when item is copied to inventory + + - - - - - + + - - - - - + + - - - - - - + + - - - - - - - + + - - - Save changes to notecard embedded in object contents - - Encoded notecard asset data - Notecard UUID - Object's UUID - Called upon finish of the upload with status information + + - - - Upload new gesture asset for an inventory gesture item - - Encoded gesture asset - Gesture inventory UUID - Callback whick will be called when upload is complete + + - - - Update an existing script in an agents Inventory - - A byte[] array containing the encoded scripts contents - the itemID of the script - if true, sets the script content to run on the mono interpreter - + + - - - Update an existing script in an task Inventory - - A byte[] array containing the encoded scripts contents - the itemID of the script - UUID of the prim containting the script - if true, sets the script content to run on the mono interpreter - if true, sets the script to running - + + - - - Rez an object from inventory - - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details + + - - - Rez an object from inventory - - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - UUID of group to own the object + + - - - Rez an object from inventory - - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - UUID of group to own the object - User defined queryID to correlate replies - If set to true, the CreateSelected flag - will be set on the rezzed object + + - - - Rez an object from inventory - - Simulator to place object in - TaskID object when rezzed - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - UUID of group to own the object - User defined queryID to correlate replies - If set to true, the CreateSelected flag - will be set on the rezzed object + + - - - DeRez an object from the simulator to the agents Objects folder in the agents Inventory - - The simulator Local ID of the object - If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed + + - - - DeRez an object from the simulator and return to inventory - - The simulator Local ID of the object - The type of destination from the enum - The destination inventory folders -or- - if DeRezzing object to a tasks Inventory, the Tasks - The transaction ID for this request which - can be used to correlate this request with other packets - If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed + + - - - Rez an item from inventory to its previous simulator location - - - - - + + - - - Give an inventory item to another avatar - - The of the item to give - The name of the item - The type of the item from the enum - The of the recipient - true to generate a beameffect during transfer + + - - - Give an inventory Folder with contents to another avatar - - The of the Folder to give - The name of the folder - The type of the item from the enum - The of the recipient - true to generate a beameffect during transfer + + - - - Copy or move an from agent inventory to a task (primitive) inventory - - The target object - The item to copy or move from inventory - - For items with copy permissions a copy of the item is placed in the tasks inventory, - for no-copy items the object is moved to the tasks inventory + + - - - Retrieve a listing of the items contained in a task (Primitive) - - The tasks - The tasks simulator local ID - milliseconds to wait for reply from simulator - A list containing the inventory items inside the task or null - if a timeout occurs - This request blocks until the response from the simulator arrives - or timeoutMS is exceeded + + - - - Request the contents of a tasks (primitives) inventory from the - current simulator - - The LocalID of the object - + + - - - Request the contents of a tasks (primitives) inventory - - The simulator Local ID of the object - A reference to the simulator object that contains the object - + + - - - Move an item from a tasks (Primitive) inventory to the specified folder in the avatars inventory - - LocalID of the object in the simulator - UUID of the task item to move - The ID of the destination folder in this agents inventory - Simulator Object - Raises the event + + - - - Remove an item from an objects (Prim) Inventory - - LocalID of the object in the simulator - UUID of the task item to remove - Simulator Object - You can confirm the removal by comparing the tasks inventory serial before and after the - request with the request combined with - the event + + - - - Copy an InventoryScript item from the Agents Inventory into a primitives task inventory - - An unsigned integer representing a primitive being simulated - An which represents a script object from the agents inventory - true to set the scripts running state to enabled - A Unique Transaction ID - - The following example shows the basic steps necessary to copy a script from the agents inventory into a tasks inventory - and assumes the script exists in the agents inventory. - - uint primID = 95899503; // Fake prim ID - UUID scriptID = UUID.Parse("92a7fe8a-e949-dd39-a8d8-1681d8673232"); // Fake Script UUID in Inventory - - Client.Inventory.FolderContents(Client.Inventory.FindFolderForType(AssetType.LSLText), Client.Self.AgentID, - false, true, InventorySortOrder.ByName, 10000); - - Client.Inventory.RezScript(primID, (InventoryItem)Client.Inventory.Store[scriptID]); - - + + - - - Request the running status of a script contained in a task (primitive) inventory - - The ID of the primitive containing the script - The ID of the script - The event can be used to obtain the results of the - request - + + - - - Send a request to set the running state of a script contained in a task (primitive) inventory - - The ID of the primitive containing the script - The ID of the script - true to set the script running, false to stop a running script - To verify the change you can use the method combined - with the event + + - - - Create a CRC from an InventoryItem - - The source InventoryItem - A uint representing the source InventoryItem as a CRC + + - - - Reverses a cheesy XORing with a fixed UUID to convert a shadow_id to an asset_id - - Obfuscated shadow_id value - Deobfuscated asset_id value + + - - - Does a cheesy XORing with a fixed UUID to convert an asset_id to a shadow_id - - asset_id value to obfuscate - Obfuscated shadow_id value + + - - - Wrapper for creating a new object - - The type of item from the enum - The of the newly created object - An object with the type and id passed + + - - - Parse the results of a RequestTaskInventory() response - - A string which contains the data from the task reply - A List containing the items contained within the tasks inventory + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - - UpdateCreateInventoryItem packets are received when a new inventory item - is created. This may occur when an object that's rezzed in world is - taken into inventory, when an item is created using the CreateInventoryItem - packet, or when an object is purchased - - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - an inventory object sent by another avatar or primitive + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - - Get this agents Inventory data - + + - - - Callback for inventory item creation finishing - - Whether the request to create an inventory - item succeeded or not - Inventory item being created. If success is - false this will be null + + - - - Callback for an inventory item being create from an uploaded asset - - true if inventory item creation was successful - - - + + - - - - - + + - - - Reply received when uploading an inventory asset - - Has upload been successful - Error message if upload failed - Inventory asset UUID - New asset UUID + + - - - Delegate that is invoked when script upload is completed - - Has upload succeded (note, there still might be compile errors) - Upload status message - Is compilation successful - If compilation failed, list of error messages, null on compilation success - Script inventory UUID - Script's new asset UUID + + - - Set to true to accept offer, false to decline it + + - - The folder to accept the inventory into, if null default folder for will be used + + - - - Callback when an inventory object is accepted and received from a - task inventory. This is the callback in which you actually get - the ItemID, as in ObjectOfferedCallback it is null when received - from a task. - + + - - - Attempts to convert an LLSD structure to a known Packet type - - Event name, this must match an actual - packet name for a Packet to be successfully built - LLSD to convert to a Packet - A Packet on success, otherwise null + + - - - Class that handles the local asset cache - + + - - - Default constructor - - A reference to the GridClient object + + - - - Disposes cleanup timer - + + - - - Only create timer when needed - + + - - - Return bytes read from the local asset cache, null if it does not exist - - UUID of the asset we want to get - Raw bytes of the asset, or null on failure + + - - - Returns ImageDownload object of the - image from the local image cache, null if it does not exist - - UUID of the image we want to get - ImageDownload object containing the image, or null on failure + + - - - Constructs a file name of the cached asset - - UUID of the asset - String with the file name of the cahced asset + + - - - Constructs a file name of the static cached asset - - UUID of the asset - String with the file name of the static cached asset + + - - - Saves an asset to the local cache - - UUID of the asset - Raw bytes the asset consists of - Weather the operation was successfull + + - - - Get the file name of the asset stored with gived UUID - - UUID of the asset - Null if we don't have that UUID cached on disk, file name if found in the cache folder + + - - - Checks if the asset exists in the local cache - - UUID of the asset - True is the asset is stored in the cache, otherwise false + + - - - Wipes out entire cache - + + - - - Brings cache size to the 90% of the max size - + + - - - Asynchronously brings cache size to the 90% of the max size - + + - - - Adds up file sizes passes in a FileInfo array - + + - - - Checks whether caching is enabled - + + - - - Periodically prune the cache - + + - - - Nicely formats file sizes - - Byte size we want to output - String with humanly readable file size + + - - - Allows setting weather to periodicale prune the cache if it grows too big - Default is enabled, when caching is enabled - + + - - - How long (in ms) between cache checks (default is 5 min.) - + + - - - Helper class for sorting files by their last accessed time - + + - - - Throttles the network traffic for various different traffic types. - Access this class through GridClient.Throttle - + + - - - Default constructor, uses a default high total of 1500 KBps (1536000) - + + - - - Constructor that decodes an existing AgentThrottle packet in to - individual values - - Reference to the throttle data in an AgentThrottle - packet - Offset position to start reading at in the - throttle data - This is generally not needed in clients as the server will - never send a throttle packet to the client + + - - - Send an AgentThrottle packet to the current server using the - current values - + + - - - Send an AgentThrottle packet to the specified server using the - current values - + + - - - Convert the current throttle values to a byte array that can be put - in an AgentThrottle packet - - Byte array containing all the throttle values + + - - Maximum bits per second for resending unacknowledged packets + + - - Maximum bits per second for LayerData terrain + + - - Maximum bits per second for LayerData wind data + + - - Maximum bits per second for LayerData clouds + + - - Unknown, includes object data + + - - Maximum bits per second for textures + + - - Maximum bits per second for downloaded assets + + - - Maximum bits per second the entire connection, divided up - between invidiual streams using default multipliers + + - - - Represents a Callingcard with AvatarID and Position vector - + + - - UUID of the Callingcard target avatar + + - - Construct an Asset of type Callingcard + + - - - Construct an Asset object of type Callingcard - - A unique specific to this asset - A byte array containing the raw asset data + + - - - Constuct an asset of type Callingcard - - UUID of the target avatar + + - - - Encode the raw contents of a string with the specific Callingcard format - + + - - - Decode the raw asset data, populating the AvatarID and Position - - true if the AssetData was successfully decoded to a UUID and Vector + + - - Override the base classes AssetType + + - - - Constants for the archiving module - + + - - - Path for region settings. - + + - - - The location of the archive control file - + + - - - Path for the assets held in an archive - + + - - - Path for the prims file - + + - - - Path for terrains. Technically these may be assets, but I think it's quite nice to split them out. - + + - - - Path for region settings. - + + - - - The character the separates the uuid from extension information in an archived asset filename - + + - - - Extensions used for asset types in the archive - + + - - - Checks the instance back into the object pool - + + - - - Returns an instance of the class that has been checked out of the Object Pool. - + + - - - Creates a new instance of the ObjectPoolBase class. Initialize MUST be called - after using this constructor. - + + - - - Creates a new instance of the ObjectPool Base class. - - The object pool is composed of segments, which - are allocated whenever the size of the pool is exceeded. The number of items - in a segment should be large enough that allocating a new segmeng is a rare - thing. For example, on a server that will have 10k people logged in at once, - the receive buffer object pool should have segment sizes of at least 1000 - byte arrays per segment. - - The minimun number of segments that may exist. - Perform a full GC.Collect whenever a segment is allocated, and then again after allocation to compact the heap. - The frequency which segments are checked to see if they're eligible for cleanup. + + - - - Forces the segment cleanup algorithm to be run. This method is intended - primarly for use from the Unit Test libraries. - + + - - - Responsible for allocate 1 instance of an object that will be stored in a segment. - - An instance of whatever objec the pool is pooling. + + - - - Checks in an instance of T owned by the object pool. This method is only intended to be called - by the WrappedObject class. - - The segment from which the instance is checked out. - The instance of T to check back into the segment. + + - - - Checks an instance of T from the pool. If the pool is not sufficient to - allow the checkout, a new segment is created. - - A WrappedObject around the instance of T. To check - the instance back into the segment, be sureto dispose the WrappedObject - when finished. + + - - - The total number of segments created. Intended to be used by the Unit Tests. - + + - - - The number of items that are in a segment. Items in a segment - are all allocated at the same time, and are hopefully close to - each other in the managed heap. - + + - - - The minimum number of segments. When segments are reclaimed, - this number of segments will always be left alone. These - segments are allocated at startup. - + + - - - The age a segment must be before it's eligible for cleanup. - This is used to prevent thrash, and typical values are in - the 5 minute range. - + + - - - The frequence which the cleanup thread runs. This is typically - expected to be in the 5 minute range. - + + - - - Main class to expose grid functionality to clients. All of the - classes needed for sending and receiving data are accessible through - this class. - - - - // Example minimum code required to instantiate class and - // connect to a simulator. - using System; - using System.Collections.Generic; - using System.Text; - using OpenMetaverse; - - namespace FirstBot - { - class Bot - { - public static GridClient Client; - static void Main(string[] args) - { - Client = new GridClient(); // instantiates the GridClient class - // to the global Client object - // Login to Simulator - Client.Network.Login("FirstName", "LastName", "Password", "FirstBot", "1.0"); - // Wait for a Keypress - Console.ReadLine(); - // Logout of simulator - Client.Network.Logout(); - } - } - } - - + + - - Networking subsystem + + - - Settings class including constant values and changeable - parameters for everything + + - - Parcel (subdivided simulator lots) subsystem + + - - Our own avatars subsystem + + - - Other avatars subsystem + + - - Estate subsystem + + - - Friends list subsystem + + - - Grid (aka simulator group) subsystem + + - - Object subsystem + + - - Group subsystem + + - - Asset subsystem + + - - Appearance subsystem + + - - Inventory subsystem + + - - Directory searches including classifieds, people, land - sales, etc + + - - Handles land, wind, and cloud heightmaps + + - - Handles sound-related networking + + - - Throttling total bandwidth usage, or allocating bandwidth - for specific data stream types + + - - - Default constructor - + + - - - Return the full name of this instance - - Client avatars full name + + - - Describes tasks returned in LandStatReply + + - - - Estate level administration and utilities - + + - - Textures for each of the four terrain height levels + + - - Upper/lower texture boundaries for each corner of the sim + + - - - Constructor for EstateTools class - - + + - - The event subscribers. null if no subcribers + + - - Raises the TopCollidersReply event - A TopCollidersReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the TopScriptsReply event - A TopScriptsReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the EstateUsersReply event - A EstateUsersReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the EstateGroupsReply event - A EstateGroupsReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the EstateManagersReply event - A EstateManagersReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the EstateBansReply event - A EstateBansReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the EstateCovenantReply event - A EstateCovenantReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the EstateUpdateInfoReply event - A EstateUpdateInfoReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - - Requests estate information such as top scripts and colliders - - - - - + + - - Requests estate settings, including estate manager and access/ban lists + + - - Requests the "Top Scripts" list for the current region + + - - Requests the "Top Colliders" list for the current region + + - - - Set several estate specific configuration variables - - The Height of the waterlevel over the entire estate. Defaults to 20 - The maximum height change allowed above the baked terrain. Defaults to 4 - The minimum height change allowed below the baked terrain. Defaults to -4 - true to use - if True forces the sun position to the position in SunPosition - The current position of the sun on the estate, or when FixedSun is true the static position - the sun will remain. 6.0 = Sunrise, 30.0 = Sunset + + - - - Request return of objects owned by specified avatar - - The Agents owning the primitives to return - specify the coverage and type of objects to be included in the return - true to perform return on entire estate + + - - - - + + - - - Used for setting and retrieving various estate panel settings - - EstateOwnerMessage Method field - List of parameters to include + + - - - Kick an avatar from an estate - - Key of Agent to remove + + - - - Ban an avatar from an estate - Key of Agent to remove - Ban user from this estate and all others owned by the estate owner + + - - Unban an avatar from an estate - Key of Agent to remove - /// Unban user from this estate and all others owned by the estate owner + + - - - Send a message dialog to everyone in an entire estate - - Message to send all users in the estate + + - - - Send a message dialog to everyone in a simulator - - Message to send all users in the simulator + + - - - Send an avatar back to their home location - - Key of avatar to send home + + + + + + + + - - - Begin the region restart process - + + - - - Cancels a region restart - + + - - Estate panel "Region" tab settings + + - - Estate panel "Debug" tab settings + + - - Used for setting the region's terrain textures for its four height levels - - - - + + - - Used for setting sim terrain texture heights + + - - Requests the estate covenant + + - - - Upload a terrain RAW file - - A byte array containing the encoded terrain data - The name of the file being uploaded - The Id of the transfer request + + - - - Teleports all users home in current Estate - + + - - - Remove estate manager - Key of Agent to Remove - removes manager to this estate and all others owned by the estate owner + + - - - Add estate manager - Key of Agent to Add - Add agent as manager to this estate and all others owned by the estate owner + + - - - Add's an agent to the estate Allowed list - Key of Agent to Add - Add agent as an allowed reisdent to All estates if true + + - - - Removes an agent from the estate Allowed list - Key of Agent to Remove - Removes agent as an allowed reisdent from All estates if true + + - - - - Add's a group to the estate Allowed list - Key of Group to Add - Add Group as an allowed group to All estates if true + + - - - - Removes a group from the estate Allowed list - Key of Group to Remove - Removes Group as an allowed Group from All estates if true + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Used in the ReportType field of a LandStatRequest + + - - Used by EstateOwnerMessage packets + + - - Used by EstateOwnerMessage packets + + - - - - + + - - No flags set + + - - Only return targets scripted objects + + - - Only return targets objects if on others land + + - - Returns target's scripted objects and objects on other parcels + + - - Ground texture settings for each corner of the region + + - - Used by GroundTextureHeightSettings + + - - The high and low texture thresholds for each corner of the sim + + - - Raised on LandStatReply when the report type is for "top colliders" + + - - Construct a new instance of the TopCollidersReplyEventArgs class - The number of returned items in LandStatReply - Dictionary of Object UUIDs to tasks returned in LandStatReply + + - - - The number of returned items in LandStatReply - + + - - - A Dictionary of Object UUIDs to tasks returned in LandStatReply - + + - - Raised on LandStatReply when the report type is for "top Scripts" + + - - Construct a new instance of the TopScriptsReplyEventArgs class - The number of returned items in LandStatReply - Dictionary of Object UUIDs to tasks returned in LandStatReply + + - - - The number of scripts returned in LandStatReply - + + - - - A Dictionary of Object UUIDs to tasks returned in LandStatReply - + + - - Returned, along with other info, upon a successful .RequestInfo() + + - - Construct a new instance of the EstateBansReplyEventArgs class - The estate's identifier on the grid - The number of returned items in LandStatReply - User UUIDs banned + + - - - The identifier of the estate - + + - - - The number of returned itmes - + + - - - List of UUIDs of Banned Users - + + - - Returned, along with other info, upon a successful .RequestInfo() + + - - Construct a new instance of the EstateUsersReplyEventArgs class - The estate's identifier on the grid - The number of users - Allowed users UUIDs + + - - - The identifier of the estate - + + - - - The number of returned items - + + - - - List of UUIDs of Allowed Users - + + - - Returned, along with other info, upon a successful .RequestInfo() + + - - Construct a new instance of the EstateGroupsReplyEventArgs class - The estate's identifier on the grid - The number of Groups - Allowed Groups UUIDs + + - - - The identifier of the estate - + + - - - The number of returned items - + + - - - List of UUIDs of Allowed Groups - + + - - Returned, along with other info, upon a successful .RequestInfo() + + - - Construct a new instance of the EstateManagersReplyEventArgs class - The estate's identifier on the grid - The number of Managers - Managers UUIDs + + - - - The identifier of the estate - + + - - - The number of returned items - + + - - - List of UUIDs of the Estate's Managers - + + - - Returned, along with other info, upon a successful .RequestInfo() + + - - Construct a new instance of the EstateCovenantReplyEventArgs class - The Covenant ID - The timestamp - The estate's name - The Estate Owner's ID (can be a GroupID) + + - - - The Covenant - + + - - - The timestamp - + + - - - The Estate name - + + - - - The Estate Owner's ID (can be a GroupID) - + + - - Returned, along with other info, upon a successful .RequestInfo() + + - - Construct a new instance of the EstateUpdateInfoReplyEventArgs class - The estate's name - The Estate Owners ID (can be a GroupID) - The estate's identifier on the grid - + + + + + + + + + + + - - - The estate's name - + + - - - The Estate Owner's ID (can be a GroupID) - + + - - - The identifier of the estate on the grid - + + - - + + - - - Archives assets - + + - - - Archive assets - + + - - - Archive the assets given to this archiver to the given archive. - - + + - - - Write an assets metadata file to the given archive - - + + - - - Write asset data files to the given archive - - + + - - - Access to the data server which allows searching for land, events, people, etc - + + - - The event subscribers. null if no subcribers + + - - Raises the EventInfoReply event - An EventInfoReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the DirEventsReply event - An DirEventsReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the PlacesReply event - A PlacesReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the DirPlacesReply event - A DirPlacesReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the DirClassifiedsReply event - A DirClassifiedsReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the DirGroupsReply event - A DirGroupsReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the DirPeopleReply event - A DirPeopleReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the DirLandReply event - A DirLandReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - - Constructs a new instance of the DirectoryManager class - - An instance of GridClient + + - - - Query the data server for a list of classified ads containing the specified string. - Defaults to searching for classified placed in any category, and includes PG, Adult and Mature - results. - - Responses are sent 16 per response packet, there is no way to know how many results a query reply will contain however assuming - the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received - - The event is raised when a response is received from the simulator - - A string containing a list of keywords to search for - A UUID to correlate the results when the event is raised + + - - - Query the data server for a list of classified ads which contain specified keywords (Overload) - - The event is raised when a response is received from the simulator - - A string containing a list of keywords to search for - The category to search - A set of flags which can be ORed to modify query options - such as classified maturity rating. - A UUID to correlate the results when the event is raised - - Search classified ads containing the key words "foo" and "bar" in the "Any" category that are either PG or Mature - - UUID searchID = StartClassifiedSearch("foo bar", ClassifiedCategories.Any, ClassifiedQueryFlags.PG | ClassifiedQueryFlags.Mature); - - - - Responses are sent 16 at a time, there is no way to know how many results a query reply will contain however assuming - the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received - + + - - - Starts search for places (Overloaded) - - The event is raised when a response is received from the simulator - - Search text - Each request is limited to 100 places - being returned. To get the first 100 result entries of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - A UUID to correlate the results when the event is raised + + - - - Queries the dataserver for parcels of land which are flagged to be shown in search - - The event is raised when a response is received from the simulator - - A string containing a list of keywords to search for separated by a space character - A set of flags which can be ORed to modify query options - such as classified maturity rating. - The category to search - Each request is limited to 100 places - being returned. To get the first 100 result entries of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - A UUID to correlate the results when the event is raised - - Search places containing the key words "foo" and "bar" in the "Any" category that are either PG or Adult - - UUID searchID = StartDirPlacesSearch("foo bar", DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeAdult, ParcelCategory.Any, 0); - - - - Additional information on the results can be obtained by using the ParcelManager.InfoRequest method - + + - - - Starts a search for land sales using the directory - - The event is raised when a response is received from the simulator - - What type of land to search for. Auction, - estate, mainland, "first land", etc - The OnDirLandReply event handler must be registered before - calling this function. There is no way to determine how many - results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each query. + + - - - Starts a search for land sales using the directory - - The event is raised when a response is received from the simulator - - What type of land to search for. Auction, - estate, mainland, "first land", etc - Maximum price to search for - Maximum area to search for - Each request is limited to 100 parcels - being returned. To get the first 100 parcels of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - The OnDirLandReply event handler must be registered before - calling this function. There is no way to determine how many - results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each query. + + - - - Send a request to the data server for land sales listings - - - Flags sent to specify query options - - Available flags: - Specify the parcel rating with one or more of the following: - IncludePG IncludeMature IncludeAdult - - Specify the field to pre sort the results with ONLY ONE of the following: - PerMeterSort NameSort AreaSort PricesSort - - Specify the order the results are returned in, if not specified the results are pre sorted in a Descending Order - SortAsc - - Specify additional filters to limit the results with one or both of the following: - LimitByPrice LimitByArea - - Flags can be combined by separating them with the | (pipe) character - - Additional details can be found in - - What type of land to search for. Auction, - Estate or Mainland - Maximum price to search for when the - DirFindFlags.LimitByPrice flag is specified in findFlags - Maximum area to search for when the - DirFindFlags.LimitByArea flag is specified in findFlags - Each request is limited to 100 parcels - being returned. To get the first 100 parcels of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - The event will be raised with the response from the simulator - - There is no way to determine how many results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each reply. - - Any land set for sale to either anybody or specific to the connected agent will be included in the - results if the land is included in the query - - - // request all mainland, any maturity rating that is larger than 512 sq.m - StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByArea | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, SearchTypeFlags.Mainland, 0, 512, 0); - + + + + + - - - Search for Groups - - The name or portion of the name of the group you wish to search for - Start from the match number - + + - - - Search for Groups - - The name or portion of the name of the group you wish to search for - Start from the match number - Search flags - + + - - - Search the People directory for other avatars - - The name or portion of the name of the avatar you wish to search for - - + + - - - Search Places for parcels of land you personally own - + + - - - Searches Places for land owned by the specified group - - ID of the group you want to recieve land list for (You must be a member of the group) - Transaction (Query) ID which can be associated with results from your request. + + - - - Search the Places directory for parcels that are listed in search and contain the specified keywords - - A string containing the keywords to search for - Transaction (Query) ID which can be associated with results from your request. + + - - - Search Places - All Options - - One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc. - One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer - A string containing a list of keywords to search for separated by a space character - String Simulator Name to search in - LLUID of group you want to recieve results for - Transaction (Query) ID which can be associated with results from your request. - Transaction (Query) ID which can be associated with results from your request. + + - - - Search All Events with specifid searchText in all categories, includes PG, Mature and Adult - - A string containing a list of keywords to search for separated by a space character - Each request is limited to 100 entries - being returned. To get the first group of entries of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - UUID of query to correlate results in callback. + + - - - Search Events - - A string containing a list of keywords to search for separated by a space character - One or more of the following flags: DateEvents, IncludePG, IncludeMature, IncludeAdult - from the Enum - - Multiple flags can be combined by separating the flags with the | (pipe) character - "u" for in-progress and upcoming events, -or- number of days since/until event is scheduled - For example "0" = Today, "1" = tomorrow, "2" = following day, "-1" = yesterday, etc. - Each request is limited to 100 entries - being returned. To get the first group of entries of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - EventCategory event is listed under. - UUID of query to correlate results in callback. + + - - Requests Event Details - ID of Event returned from the method + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming event message - The Unique Capabilities Key - The event message containing the data - The simulator the message originated from + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming event message - The Unique Capabilities Key - The event message containing the data - The simulator the message originated from + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Classified Ad categories + + - - Classified is listed in the Any category + + - - Classified is shopping related + + - - Classified is + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - Event Categories + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - Query Flags used in many of the DirectoryManager methods to specify which query to execute and how to return the results. - - Flags can be combined using the | (pipe) character, not all flags are available in all queries - + + - - Query the People database + + - - + + - - + + - - Query the Groups database + + - - Query the Events database + + - - Query the land holdings database for land owned by the currently connected agent + + - - + + - - Query the land holdings database for land which is owned by a Group + + - - Specifies the query should pre sort the results based upon traffic - when searching the Places database + + - - + + - - + + - - + + - - + + - - Specifies the query should pre sort the results in an ascending order when searching the land sales database. - This flag is only used when searching the land sales database + + - - Specifies the query should pre sort the results using the SalePrice field when searching the land sales database. - This flag is only used when searching the land sales database + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - Specifies the query should pre sort the results by calculating the average price/sq.m (SalePrice / Area) when searching the land sales database. - This flag is only used when searching the land sales database + + - - Specifies the query should pre sort the results using the ParcelSize field when searching the land sales database. - This flag is only used when searching the land sales database + + - - Specifies the query should pre sort the results using the Name field when searching the land sales database. - This flag is only used when searching the land sales database + + - - When set, only parcels less than the specified Price will be included when searching the land sales database. - This flag is only used when searching the land sales database + + - - When set, only parcels greater than the specified Size will be included when searching the land sales database. - This flag is only used when searching the land sales database + + - - + + - - + + - - Include PG land in results. This flag is used when searching both the Groups, Events and Land sales databases + + - - Include Mature land in results. This flag is used when searching both the Groups, Events and Land sales databases + + - - Include Adult land in results. This flag is used when searching both the Groups, Events and Land sales databases + + - - + + - - - Land types to search dataserver for - + + - - Search Auction, Mainland and Estate + + - - Land which is currently up for auction + + - - Parcels which are on the mainland (Linden owned) continents + + - - Parcels which are on privately owned simulators + + - - - The content rating of the event - + + - - Event is PG + + - - Event is Mature + + - - Event is Adult + + - - - Classified Ad Options - - There appear to be two formats the flags are packed in. - This set of flags is for the newer style + + - - + + - - + + - - + + - - + + - - + + - - - Classified ad query options - + + - - Include all ads in results + + - - Include PG ads in results + + - - Include Mature ads in results + + - - Include Adult ads in results + + - - - The For Sale flag in PlacesReplyData - + + - - Parcel is not listed for sale + + - - Parcel is For Sale + + - - - A classified ad on the grid - + + - - UUID for this ad, useful for looking up detailed - information about it + + - - The title of this classified ad + + - - Flags that show certain options applied to the classified + + - - Creation date of the ad + + - - Expiration date of the ad + + - - Price that was paid for this ad + + - - Print the struct data as a string - A string containing the field name, and field value + + - - - A parcel retrieved from the dataserver such as results from the - "For-Sale" listings or "Places" Search - + + - - The unique dataserver parcel ID - This id is used to obtain additional information from the entry - by using the method + + - - A string containing the name of the parcel + + - - The size of the parcel - This field is not returned for Places searches + + - - The price of the parcel - This field is not returned for Places searches + + - - If True, this parcel is flagged to be auctioned + + - - If true, this parcel is currently set for sale + + - - Parcel traffic + + - - Print the struct data as a string - A string containing the field name, and field value + + - - - An Avatar returned from the dataserver - + + - - Online status of agent - This field appears to be obsolete and always returns false + + - - The agents first name + + - - The agents last name + + - - The agents + + - - Print the struct data as a string - A string containing the field name, and field value + + - - - Response to a "Groups" Search - + + - - The Group ID + + - - The name of the group + + - - The current number of members + + - - Print the struct data as a string - A string containing the field name, and field value + + - - - Parcel information returned from a request - - Represents one of the following: - A parcel of land on the grid that has its Show In Search flag set - A parcel of land owned by the agent making the request - A parcel of land owned by a group the agent making the request is a member of - - - In a request for Group Land, the First record will contain an empty record - - Note: This is not the same as searching the land for sale data source - + + - - The ID of the Agent of Group that owns the parcel + + - - The name + + - - The description + + - - The Size of the parcel + + - - The billable Size of the parcel, for mainland - parcels this will match the ActualArea field. For Group owned land this will be 10 percent smaller - than the ActualArea. For Estate land this will always be 0 + + - - Indicates the ForSale status of the parcel + + - - The Gridwide X position + + - - The Gridwide Y position + + - - The Z position of the parcel, or 0 if no landing point set + + - - The name of the Region the parcel is located in + + - - The Asset ID of the parcels Snapshot texture + + - - The calculated visitor traffic + + - - The billing product SKU - Known values are: - - 023Mainland / Full Region - 024Estate / Full Region - 027Estate / Openspace - 029Estate / Homestead - 129Mainland / Homestead (Linden Owned) - - + + - - No longer used, will always be 0 + + - - Get a SL URL for the parcel - A string, containing a standard SLURL + + - - Print the struct data as a string - A string containing the field name, and field value + + - - - An "Event" Listing summary - + + - - The ID of the event creator + + - - The name of the event + + - - The events ID + + - - A string containing the short date/time the event will begin + + - - The event start time in Unixtime (seconds since epoch) + + - - The events maturity rating + + - - Print the struct data as a string - A string containing the field name, and field value + + - - - The details of an "Event" - + + - - The events ID + + - - The ID of the event creator + + - - The name of the event + + - - The category + + - - The events description + + - - The short date/time the event will begin + + + + + + + + - - The event start time in Unixtime (seconds since epoch) UTC adjusted + + - - The length of the event in minutes + + - - 0 if no cover charge applies + + - - The cover charge amount in L$ if applicable + + - - The name of the region where the event is being held + + - - The gridwide location of the event + + - - The maturity rating + + - - Get a SL URL for the parcel where the event is hosted - A string, containing a standard SLURL + + - - Print the struct data as a string - A string containing the field name, and field value + + - - Contains the Event data returned from the data server from an EventInfoRequest + + - - Construct a new instance of the EventInfoReplyEventArgs class - A single EventInfo object containing the details of an event + + - - - A single EventInfo object containing the details of an event - + + - - Contains the "Event" detail data returned from the data server + + - - Construct a new instance of the DirEventsReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing the "Events" returned by the search query + + - - The ID returned by + + - - A list of "Events" returned by the data server + + - - Contains the "Event" list data returned from the data server + + - - Construct a new instance of PlacesReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing the "Places" returned by the data server query + + - - The ID returned by + + - - A list of "Places" returned by the data server + + - - Contains the places data returned from the data server + + - - Construct a new instance of the DirPlacesReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing land data returned by the data server + + - - The ID returned by + + - - A list containing Places data returned by the data server + + - - Contains the classified data returned from the data server + + - - Construct a new instance of the DirClassifiedsReplyEventArgs class - A list of classified ad data returned from the data server + + - - A list containing Classified Ads returned by the data server + + - - Contains the group data returned from the data server + + - - Construct a new instance of the DirGroupsReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list of groups data returned by the data server + + - - The ID returned by + + - - A list containing Groups data returned by the data server + + - - Contains the people data returned from the data server + + - - Construct a new instance of the DirPeopleReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list of people data returned by the data server + + - - The ID returned by + + - - A list containing People data returned by the data server + + - - Contains the land sales data returned from the data server + + - - Construct a new instance of the DirLandReplyEventArgs class - A list of parcels for sale returned by the data server + + - - A list containing land forsale data returned by the data server + + - - - Reads in a byte array of an Animation Asset created by the SecondLife(tm) client. - + + - - - Rotation Keyframe count (used internally) - + + - - - Position Keyframe count (used internally) - + + - - - Animation Priority - + + - - - The animation length in seconds. - + + - - - Expression set in the client. Null if [None] is selected - + + - - - The time in seconds to start the animation - + + - - - The time in seconds to end the animation - + + - - - Loop the animation - + + - - - Meta data. Ease in Seconds. - + + - - - Meta data. Ease out seconds. - + + - - - Meta Data for the Hand Pose - + + - - - Number of joints defined in the animation - + + - - - Contains an array of joints - + + - - - Searialize an animation asset into it's joints/keyframes/meta data - - + + - - - Variable length strings seem to be null terminated in the animation asset.. but.. - use with caution, home grown. - advances the index. - - The animation asset byte array - The offset to start reading - a string + + - - - Read in a Joint from an animation asset byte array - Variable length Joint fields, yay! - Advances the index - - animation asset byte array - Byte Offset of the start of the joint - The Joint data serialized into the binBVHJoint structure + + - - - Read Keyframes of a certain type - advance i - - Animation Byte array - Offset in the Byte Array. Will be advanced - Number of Keyframes - Scaling Min to pass to the Uint16ToFloat method - Scaling Max to pass to the Uint16ToFloat method - + + - - - Determines whether the specified is equal to the current . - - - true if the specified is equal to the current ; otherwise, false. - - The to compare with the current . - The parameter is null. - 2 + + - - - Serves as a hash function for a particular type. - - - A hash code for the current . - - 2 + + - - - A Joint and it's associated meta data and keyframes - + + - - - Indicates whether this instance and a specified object are equal. - - - true if and this instance are the same type and represent the same value; otherwise, false. - - Another object to compare to. - 2 + + - - - Returns the hash code for this instance. - - - A 32-bit signed integer that is the hash code for this instance. - - 2 + + - - - Name of the Joint. Matches the avatar_skeleton.xml in client distros - + + - - - Joint Animation Override? Was the same as the Priority in testing.. - + + - - - Array of Rotation Keyframes in order from earliest to latest - + + - - - Array of Position Keyframes in order from earliest to latest - This seems to only be for the Pelvis? - + + - - - Custom application data that can be attached to a joint - + + - - - A Joint Keyframe. This is either a position or a rotation. - + + - - - Either a Vector3 position or a Vector3 Euler rotation - + + - - - Poses set in the animation metadata for the hands. - + + - - - Extract the avatar UUID encoded in a SIP URI - - - + + - - - The type of bump-mapping applied to a face - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - The level of shininess applied to a face - + + - - + + - - + + - - + + - - + + - - - The texture mapping style used for a face - + + - - + + - - + + - - + + - - + + - - - Flags in the TextureEntry block that describe which properties are - set - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - Permissions for control of object media - + + - - - Style of cotrols that shold be displayed to the user - + + - - - Class representing media data for a single face - + + - - Is display of the alternative image enabled + + - - Should media auto loop + + - - Shoule media be auto played + + - - Auto scale media to prim face + + - - Should viewer automatically zoom in on the face when clicked + + - - Should viewer interpret first click as interaction with the media - or when false should the first click be treated as zoom in commadn + + - - Style of controls viewer should display when - viewer media on this face + + - - Starting URL for the media + + - - Currently navigated URL + + - - Media height in pixes + + - - Media width in pixels + + - - Who can controls the media + + - - Who can interact with the media + + - - Is URL whitelist enabled + + - - Array of URLs that are whitelisted + + - - - Serialize to OSD - - OSDMap with the serialized data + + - - - Deserialize from OSD data - - Serialized OSD data - Deserialized object + + - - - Represents an that represents an avatars body ie: Hair, Etc. - + + - - Initializes a new instance of an AssetBodyPart object + + - - Initializes a new instance of an AssetBodyPart object with parameters - A unique specific to this asset - A byte array containing the raw asset data + + - - Override the base classes AssetType + + - - - Simulator (region) properties - + + - - No flags set + + - - Agents can take damage and be killed + + - - Landmarks can be created here + + - - Home position can be set in this sim + + - - Home position is reset when an agent teleports away + + - - Sun does not move + + - - No object, land, etc. taxes + + - - Disable heightmap alterations (agents can still plant - foliage) + + - - Land cannot be released, sold, or purchased + + - - All content is wiped nightly + + - - Unknown: Related to the availability of an overview world map tile.(Think mainland images when zoomed out.) + + - - Unknown: Related to region debug flags. Possibly to skip processing of agent interaction with world. + + - - Region does not update agent prim interest lists. Internal debugging option. + + - - No collision detection for non-agent objects + + - - No scripts are ran + + - - All physics processing is turned off + + - - Region can be seen from other regions on world map. (Legacy world map option?) + + - - Region can be seen from mainland on world map. (Legacy world map option?) + + - - Agents not explicitly on the access list can visit the region. + + - - Traffic calculations are not run across entire region, overrides parcel settings. + + - - Flight is disabled (not currently enforced by the sim) + + - - Allow direct (p2p) teleporting + + - - Estate owner has temporarily disabled scripting + + - - Restricts the usage of the LSL llPushObject function, applies to whole region. + + - - Deny agents with no payment info on file + + - - Deny agents with payment info on file + + - - Deny agents who have made a monetary transaction + + - - Parcels within the region may be joined or divided by anyone, not just estate owners/managers. + + - - Abuse reports sent from within this region are sent to the estate owner defined email. + + - - Region is Voice Enabled + + - - Removes the ability from parcel owners to set their parcels to show in search. + + - - Deny agents who have not been age verified from entering the region. + + - - - Region protocol flags - + + - - Nothing special + + - - Region supports Server side Appearance + + - - Viewer supports Server side Appearance + + - - - Access level for a simulator - + + + + + - - Unknown or invalid access level + + - - Trial accounts allowed + + - - PG rating + + - - Mature rating + + - - Adult rating + + - - Simulator is offline + + - - Simulator does not exist + + - - - - + + - - A public reference to the client that this Simulator object - is attached to + + - - A Unique Cache identifier for this simulator + + - - The capabilities for this simulator + + - - + + - - The current version of software this simulator is running + + - - + + - - A 64x64 grid of parcel coloring values. The values stored - in this array are of the type + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - true if your agent has Estate Manager rights on this region + + - - + + - - + + - - + + - - Statistics information for this simulator and the - connection to the simulator, calculated by the simulator itself - and the library + + - - The regions Unique ID + + - - The physical data center the simulator is located - Known values are: - - Dallas - Chandler - SF - - + + - - The CPU Class of the simulator - Most full mainland/estate sims appear to be 5, - Homesteads and Openspace appear to be 501 + + - - The number of regions sharing the same CPU as this one - "Full Sims" appear to be 1, Homesteads appear to be 4 + + - - The billing product name - Known values are: - - Mainland / Full Region (Sku: 023) - Estate / Full Region (Sku: 024) - Estate / Openspace (Sku: 027) - Estate / Homestead (Sku: 029) - Mainland / Homestead (Sku: 129) (Linden Owned) - Mainland / Linden Homes (Sku: 131) - - + + - - The billing product SKU - Known values are: - - 023 Mainland / Full Region - 024 Estate / Full Region - 027 Estate / Openspace - 029 Estate / Homestead - 129 Mainland / Homestead (Linden Owned) - 131 Linden Homes / Full Region - - + + - - - Flags indicating which protocols this region supports - + + - - The current sequence number for packets sent to this - simulator. Must be Interlocked before modifying. Only - useful for applications manipulating sequence numbers + + - - - A thread-safe dictionary containing avatars in a simulator - + + - - - A thread-safe dictionary containing primitives in a simulator - + + - - - Checks simulator parcel map to make sure it has downloaded all data successfully - - true if map is full (contains no 0's) + + - - - Is it safe to send agent updates to this sim - AgentMovementComplete message received - + + - - Used internally to track sim disconnections + + - - Event that is triggered when the simulator successfully - establishes a connection + + - - Whether this sim is currently connected or not. Hooked up - to the property Connected + + - - Coarse locations of avatars in this simulator + + - - AvatarPositions key representing TrackAgent target + + - - Sequence numbers of packets we've received - (for duplicate checking) + + - - Packets we sent out that need ACKs from the simulator + + - - Sequence number for pause/resume + + - - Indicates if UDP connection to the sim is fully established + + - - - - - Reference to the GridClient object - IPEndPoint of the simulator - handle of the simulator + + - - - Called when this Simulator object is being destroyed - + + - - - Attempt to connect to this simulator - - Whether to move our agent in to this sim or not - True if the connection succeeded or connection status is - unknown, false if there was a failure + + - - - Initiates connection to the simulator - - Should we block until ack for this packet is recieved + + - - - Disconnect from this simulator - + + - - - Instructs the simulator to stop sending update (and possibly other) packets - + + - - - Instructs the simulator to resume sending update packets (unpause) - + + - - - Retrieve the terrain height at a given coordinate - - Sim X coordinate, valid range is from 0 to 255 - Sim Y coordinate, valid range is from 0 to 255 - The terrain height at the given point if the - lookup was successful, otherwise 0.0f - True if the lookup was successful, otherwise false + + - - - Sends a packet - - Packet to be sent + + - - - - + + - - - Returns Simulator Name as a String - - + + - - - - - + + - - - - - - + + - - - Sends out pending acknowledgements - - Number of ACKs sent + + - - - Resend unacknowledged packets - + + - - - Provides access to an internal thread-safe dictionary containing parcel - information found in this simulator - + + - - - Provides access to an internal thread-safe multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. - + + - - The IP address and port of the server + + - - Whether there is a working connection to the simulator or - not + + - - Coarse locations of avatars in this simulator + + - - AvatarPositions key representing TrackAgent target + + - - Indicates if UDP connection to the sim is fully established + + - - - Simulator Statistics - + + - - Total number of packets sent by this simulator to this agent + + - - Total number of packets received by this simulator to this agent + + - - Total number of bytes sent by this simulator to this agent + + - - Total number of bytes received by this simulator to this agent + + - - Time in seconds agent has been connected to simulator + + - - Total number of packets that have been resent + + - - Total number of resent packets recieved + + - - Total number of pings sent to this simulator by this agent + + - - Total number of ping replies sent to this agent by this simulator + + - - - Incoming bytes per second - - It would be nice to have this claculated on the fly, but - this is far, far easier + + - - - Outgoing bytes per second - - It would be nice to have this claculated on the fly, but - this is far, far easier + + - - Time last ping was sent + + - - ID of last Ping sent + + - - + + - - + + - - Current time dilation of this simulator + + - - Current Frames per second of simulator + + - - Current Physics frames per second of simulator + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - Total number of objects Simulator is simulating + + - - Total number of Active (Scripted) objects running + + - - Number of agents currently in this simulator + + - - Number of agents in neighbor simulators + + - - Number of Active scripts running in this simulator + + - - + + - - + + - - + + - - Number of downloads pending + + - - Number of uploads pending + + - - + + - - + + - - Number of local uploads pending + + - - Unacknowledged bytes in queue + + - - - Simulator handle - + + - - - Number of GridClients using this datapool - + + - - - Time that the last client disconnected from the simulator - + + - - - The cache of prims used and unused in this simulator - + + - - - Shared parcel info only when POOL_PARCEL_DATA == true - + + - - - Type of return to use when returning objects from a parcel - + + - - + + - - Return objects owned by parcel owner + + - - Return objects set to group + + - - Return objects not owned by parcel owner or set to group + + - - Return a specific list of objects on parcel + + - - Return objects that are marked for-sale + + - - - Blacklist/Whitelist flags used in parcels Access List - + + - - Agent is denied access + + - - Agent is granted access + + - - - The result of a request for parcel properties - + + - - No matches were found for the request + + - - Request matched a single parcel + + - - Request matched multiple parcels + + - - - Flags used in the ParcelAccessListRequest packet to specify whether - we want the access list (whitelist), ban list (blacklist), or both - + + - - Request the access list + + - - Request the ban list + + - - Request both White and Black lists + + - - - Sequence ID in ParcelPropertiesReply packets (sent when avatar - tries to cross a parcel border) - + + - - Parcel is currently selected + + - - Parcel restricted to a group the avatar is not a - member of + + - - Avatar is banned from the parcel + + - - Parcel is restricted to an access list that the - avatar is not on + + - - Response to hovering over a parcel + + - - - The tool to use when modifying terrain levels - + + - - Level the terrain + + - - Raise the terrain + + - - Lower the terrain + + - - Smooth the terrain + + - - Add random noise to the terrain + + - - Revert terrain to simulator default + + - - - The tool size to use when changing terrain levels - + + - - Small + + - - Medium + + - - Large + + - - - Reasons agent is denied access to a parcel on the simulator - + + - - Agent is not denied, access is granted + + - - Agent is not a member of the group set for the parcel, or which owns the parcel + + - - Agent is not on the parcels specific allow list + + - - Agent is on the parcels ban list + + - - Unknown + + - - Agent is not age verified and parcel settings deny access to non age verified avatars + + - - - Parcel overlay type. This is used primarily for highlighting and - coloring which is why it is a single integer instead of a set of - flags - - These values seem to be poorly thought out. The first three - bits represent a single value, not flags. For example Auction (0x05) is - not a combination of OwnedByOther (0x01) and ForSale(0x04). However, - the BorderWest and BorderSouth values are bit flags that get attached - to the value stored in the first three bits. Bits four, five, and six - are unused + + - - Public land + + - - Land is owned by another avatar + + - - Land is owned by a group + + - - Land is owned by the current avatar + + - - Land is for sale + + - - Land is being auctioned + + - - Land is private + + - - To the west of this area is a parcel border + + - - To the south of this area is a parcel border + + - - - Various parcel properties - + + - - No flags set + + - - Allow avatars to fly (a client-side only restriction) + + - - Allow foreign scripts to run + + - - This parcel is for sale + + - - Allow avatars to create a landmark on this parcel + + - - Allows all avatars to edit the terrain on this parcel + + - - Avatars have health and can take damage on this parcel. - If set, avatars can be killed and sent home here + + - - Foreign avatars can create objects here + + - - All objects on this parcel can be purchased + + - - Access is restricted to a group + + - - Access is restricted to a whitelist + + - - Ban blacklist is enabled + + - - Unknown + + - - List this parcel in the search directory + + - - Allow personally owned parcels to be deeded to group + + - - If Deeded, owner contributes required tier to group parcel is deeded to + + - - Restrict sounds originating on this parcel to the - parcel boundaries + + - - Objects on this parcel are sold when the land is - purchsaed + + - - Allow this parcel to be published on the web + + - - The information for this parcel is mature content + + - - The media URL is an HTML page + + - - The media URL is a raw HTML string + + - - Restrict foreign object pushes + + - - Ban all non identified/transacted avatars + + - - Allow group-owned scripts to run + + - - Allow object creation by group members or group - objects + + - - Allow all objects to enter this parcel + + - - Only allow group and owner objects to enter this parcel + + - - Voice Enabled on this parcel + + - - Use Estate Voice channel for Voice on this parcel + + - - Deny Age Unverified Users + + - - - Parcel ownership status - + + - - Placeholder + + - - Parcel is leased (owned) by an avatar or group + + - - Parcel is in process of being leased (purchased) by an avatar or group + + - - Parcel has been abandoned back to Governor Linden + + - - - Category parcel is listed in under search - + + - - No assigned category + + - - Linden Infohub or public area + + - - Adult themed area + + - - Arts and Culture + + - - Business + + - - Educational + + - - Gaming + + - - Hangout or Club + + - - Newcomer friendly + + - - Parks and Nature + + - - Residential + + - - Shopping + + - - Not Used? + + - - Other + + - - Not an actual category, only used for queries + + - - - Type of teleport landing for a parcel - + + - - Unset, simulator default + + - - Specific landing point set for this parcel + + - - No landing point set, direct teleports enabled for - this parcel + + - - - Parcel Media Command used in ParcelMediaCommandMessage - + + - - Stop the media stream and go back to the first frame + + - - Pause the media stream (stop playing but stay on current frame) + + - - Start the current media stream playing and stop when the end is reached + + - - Start the current media stream playing, - loop to the beginning when the end is reached and continue to play + + - - Specifies the texture to replace with video - If passing the key of a texture, it must be explicitly typecast as a key, - not just passed within double quotes. + + - - Specifies the movie URL (254 characters max) + + - - Specifies the time index at which to begin playing + + - - Specifies a single agent to apply the media command to + + - - Unloads the stream. While the stop command sets the texture to the first frame of the movie, - unload resets it to the real texture that the movie was replacing. + + - - Turn on/off the auto align feature, similar to the auto align checkbox in the parcel media properties - (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter. + + - - Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only). - Use "text/html" for HTML. + + - - Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only). - This might still not be working + + - - Sets a description for the media being displayed (1.19.1 RC0 and later only). + + - - - Some information about a parcel of land returned from a DirectoryManager search - + + - - Global Key of record + + - - Parcel Owners + + - - Name field of parcel, limited to 128 characters + + - - Description field of parcel, limited to 256 characters + + - - Total Square meters of parcel + + - - Total area billable as Tier, for group owned land this will be 10% less than ActualArea + + - - True of parcel is in Mature simulator + + - - Grid global X position of parcel + + - - Grid global Y position of parcel + + - - Grid global Z position of parcel (not used) + + - - Name of simulator parcel is located in + + - - Texture of parcels display picture + + - - Float representing calculated traffic based on time spent on parcel by avatars + + - - Sale price of parcel (not used) + + - - Auction ID of parcel + + - - - Parcel Media Information - + + - - A byte, if 0x1 viewer should auto scale media to fit object + + - - A boolean, if true the viewer should loop the media + + - - The Asset UUID of the Texture which when applied to a - primitive will display the media + + - - A URL which points to any Quicktime supported media type + + - - A description of the media + + - - An Integer which represents the height of the media + + - - An integer which represents the width of the media + + - - A string which contains the mime type of the media + + - - - Parcel of land, a portion of virtual real estate in a simulator - + + - - The total number of contiguous 4x4 meter blocks your agent owns within this parcel + + - - The total number of contiguous 4x4 meter blocks contained in this parcel owned by a group or agent other than your own + + - - Deprecated, Value appears to always be 0 + + - - Simulator-local ID of this parcel + + - - UUID of the owner of this parcel + + - - Whether the land is deeded to a group or not + + - - + + - - Date land was claimed + + - - Appears to always be zero + + - - This field is no longer used + + - - Minimum corner of the axis-aligned bounding box for this - parcel + + - - Maximum corner of the axis-aligned bounding box for this - parcel + + + + + - - Bitmap describing land layout in 4x4m squares across the - entire region + + - - Total parcel land area + + - - + + - - Maximum primitives across the entire simulator owned by the same agent or group that owns this parcel that can be used + + - - Total primitives across the entire simulator calculated by combining the allowed prim counts for each parcel - owned by the agent or group that owns this parcel + + - - Maximum number of primitives this parcel supports + + - - Total number of primitives on this parcel + + - - For group-owned parcels this indicates the total number of prims deeded to the group, - for parcels owned by an individual this inicates the number of prims owned by the individual + + - - Total number of primitives owned by the parcel group on - this parcel, or for parcels owned by an individual with a group set the - total number of prims set to that group. + + - - Total number of prims owned by other avatars that are not set to group, or not the parcel owner + + - - A bonus multiplier which allows parcel prim counts to go over times this amount, this does not affect - the max prims per simulator. e.g: 117 prim parcel limit x 1.5 bonus = 175 allowed + + - - Autoreturn value in minutes for others' objects + + - - + + - - Sale price of the parcel, only useful if ForSale is set - The SalePrice will remain the same after an ownership - transfer (sale), so it can be used to see the purchase price after - a sale if the new owner has not changed it + + - - Parcel Name + + - - Parcel Description + + - - URL For Music Stream + + - - + + - - Price for a temporary pass + + - - How long is pass valid for + + - - + + - - Key of authorized buyer + + - - Key of parcel snapshot + + - - The landing point location + + - - The landing point LookAt + + - - The type of landing enforced from the enum + + - - + + - - + + - - + + - - Access list of who is whitelisted on this - parcel + + - - Access list of who is blacklisted on this - parcel + + - - TRUE of region denies access to age unverified users + + - - true to obscure (hide) media url + + - - true to obscure (hide) music url + + - - A struct containing media details + + - - - Displays a parcel object in string format - - string containing key=value pairs of a parcel object + + - - - Defalt constructor - - Local ID of this parcel + + - - - Update the simulator with any local changes to this Parcel object - - Simulator to send updates to - Whether we want the simulator to confirm - the update with a reply packet or not + + - - - Set Autoreturn time - - Simulator to send the update to + + - - - Parcel (subdivided simulator lots) subsystem - + + - - The event subscribers. null if no subcribers + + - - Raises the ParcelDwellReply event - A ParcelDwellReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the ParcelInfoReply event - A ParcelInfoReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the ParcelProperties event - A ParcelPropertiesEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the ParcelAccessListReply event - A ParcelAccessListReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the ParcelObjectOwnersReply event - A ParcelObjectOwnersReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the SimParcelsDownloaded event - A SimParcelsDownloadedEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the ForceSelectObjectsReply event - A ForceSelectObjectsReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the ParcelMediaUpdateReply event - A ParcelMediaUpdateReplyEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the ParcelMediaCommand event - A ParcelMediaCommandEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - - Default constructor - - A reference to the GridClient object + + - - - Request basic information for a single parcel - - Simulator-local ID of the parcel + + - - - Request properties of a single parcel - - Simulator containing the parcel - Simulator-local ID of the parcel - An arbitrary integer that will be returned - with the ParcelProperties reply, useful for distinguishing between - multiple simultaneous requests + + - - - Request the access list for a single parcel - - Simulator containing the parcel - Simulator-local ID of the parcel - An arbitrary integer that will be returned - with the ParcelAccessList reply, useful for distinguishing between - multiple simultaneous requests - + + - - - Request properties of parcels using a bounding box selection - - Simulator containing the parcel - Northern boundary of the parcel selection - Eastern boundary of the parcel selection - Southern boundary of the parcel selection - Western boundary of the parcel selection - An arbitrary integer that will be returned - with the ParcelProperties reply, useful for distinguishing between - different types of parcel property requests - A boolean that is returned with the - ParcelProperties reply, useful for snapping focus to a single - parcel + + - - - Request all simulator parcel properties (used for populating the Simulator.Parcels - dictionary) - - Simulator to request parcels from (must be connected) + + - - - Request all simulator parcel properties (used for populating the Simulator.Parcels - dictionary) - - Simulator to request parcels from (must be connected) - If TRUE, will force a full refresh - Number of milliseconds to pause in between each request + + - - - Request the dwell value for a parcel - - Simulator containing the parcel - Simulator-local ID of the parcel + + - - - Send a request to Purchase a parcel of land - - The Simulator the parcel is located in - The parcels region specific local ID - true if this parcel is being purchased by a group - The groups - true to remove tier contribution if purchase is successful - The parcels size - The purchase price of the parcel - + + + + + - - - Reclaim a parcel of land - - The simulator the parcel is in - The parcels region specific local ID + + - - - Deed a parcel to a group - - The simulator the parcel is in - The parcels region specific local ID - The groups + + - - - Request prim owners of a parcel of land. - - Simulator parcel is in - The parcels region specific local ID + + - - - Return objects from a parcel - - Simulator parcel is in - The parcels region specific local ID - the type of objects to return, - A list containing object owners s to return + + - - - Subdivide (split) a parcel - - - - - - + + - - - Join two parcels of land creating a single parcel - - - - - - + + - - - Get a parcels LocalID - - Simulator parcel is in - Vector3 position in simulator (Z not used) - 0 on failure, or parcel LocalID on success. - A call to Parcels.RequestAllSimParcels is required to populate map and - dictionary. + + - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() + + - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() + + - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - How many meters + or - to lower, 1 = 1 meter - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() + + - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - How many meters + or - to lower, 1 = 1 meter - Height at which the terraform operation is acting at + + - - - Sends a request to the simulator to return a list of objects owned by specific owners - - Simulator local ID of parcel - Owners, Others, Etc - List containing keys of avatars objects to select; - if List is null will return Objects of type selectType - Response data is returned in the event + + - - - Eject and optionally ban a user from a parcel - - target key of avatar to eject - true to also ban target + + - - - Freeze or unfreeze an avatar over your land - - target key to freeze - true to freeze, false to unfreeze + + - - - Abandon a parcel of land - - Simulator parcel is in - Simulator local ID of parcel + + - - - Requests the UUID of the parcel in a remote region at a specified location - - Location of the parcel in the remote region - Remote region handle - Remote region UUID - If successful UUID of the remote parcel, UUID.Zero otherwise + + - - - Retrieves information on resources used by the parcel - - UUID of the parcel - Should per object resource usage be requested - Callback invoked when the request is complete + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a Parcel Update request + + - - Raised when the parcel your agent is located sends a ParcelMediaCommand + + - - - Parcel Accesslist - + + - - Agents + + - - + + - - Flags for specific entry in white/black lists + + - - - Owners of primitives on parcel - + + - - Prim Owners + + - - True of owner is group + + - - Total count of prims owned by OwnerID + + - - true of OwnerID is currently online and is not a group + + - - The date of the most recent prim left by OwnerID + + - - - Called once parcel resource usage information has been collected - - Indicates if operation was successfull - Parcel resource usage information + + - - Contains a parcels dwell data returned from the simulator in response to an + + - - - Construct a new instance of the ParcelDwellReplyEventArgs class - - The global ID of the parcel - The simulator specific ID of the parcel - The calculated dwell for the parcel + + - - Get the global ID of the parcel + + - - Get the simulator specific ID of the parcel + + - - Get the calculated dwell + + - - Contains basic parcel information data returned from the - simulator in response to an request + + + + + + + + + + + + + + + + + - - - Construct a new instance of the ParcelInfoReplyEventArgs class - - The object containing basic parcel info + + - - Get the object containing basic parcel info + + - - Contains basic parcel information data returned from the simulator in response to an request + + - - - Construct a new instance of the ParcelPropertiesEventArgs class - - The object containing the details - The object containing the details - The result of the request - The number of primitieves your agent is - currently selecting and or sitting on in this parcel - The user assigned ID used to correlate a request with - these results - TODO: + + - - Get the simulator the parcel is located in + + - - Get the object containing the details - If Result is NoData, this object will not contain valid data + + - - Get the result of the request + + - - Get the number of primitieves your agent is - currently selecting and or sitting on in this parcel + + - - Get the user assigned ID used to correlate a request with - these results + + - - TODO: + + - - Contains blacklist and whitelist data returned from the simulator in response to an request + + - - - Construct a new instance of the ParcelAccessListReplyEventArgs class - - The simulator the parcel is located in - The user assigned ID used to correlate a request with - these results - The simulator specific ID of the parcel - TODO: - The list containing the white/blacklisted agents for the parcel + + - - Get the simulator the parcel is located in + + - - Get the user assigned ID used to correlate a request with - these results + + - - Get the simulator specific ID of the parcel + + - - TODO: + + - - Get the list containing the white/blacklisted agents for the parcel + + - - Contains blacklist and whitelist data returned from the - simulator in response to an request + + - - - Construct a new instance of the ParcelObjectOwnersReplyEventArgs class - - The simulator the parcel is located in - The list containing prim ownership counts + + - - Get the simulator the parcel is located in + + - - Get the list containing prim ownership counts + + - - Contains the data returned when all parcel data has been retrieved from a simulator + + - - - Construct a new instance of the SimParcelsDownloadedEventArgs class - - The simulator the parcel data was retrieved from - The dictionary containing the parcel data - The multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. + + - - Get the simulator the parcel data was retrieved from + + - - A dictionary containing the parcel data where the key correlates to the ParcelMap entry + + - - Get the multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. + + - - Contains the data returned when a request + + - - - Construct a new instance of the ForceSelectObjectsReplyEventArgs class - - The simulator the parcel data was retrieved from - The list of primitive IDs - true if the list is clean and contains the information - only for a given request + + - - Get the simulator the parcel data was retrieved from + + - - Get the list of primitive IDs + + - - true if the list is clean and contains the information - only for a given request + + - - Contains data when the media data for a parcel the avatar is on changes + + - - - Construct a new instance of the ParcelMediaUpdateReplyEventArgs class - - the simulator the parcel media data was updated in - The updated media information + + - - Get the simulator the parcel media data was updated in + + - - Get the updated media information + + - - Contains the media command for a parcel the agent is currently on + + - - - Construct a new instance of the ParcelMediaCommandEventArgs class - - The simulator the parcel media command was issued in - - - The media command that was sent - + + - - Get the simulator the parcel media command was issued in + + - - + + - - + + - - Get the media command that was sent + + - - + + - - - Provides helper methods for parallelizing loops - + + - - - Executes a for loop in which iterations may run in parallel - - The loop will be started at this index - The loop will be terminated before this index is reached - Method body to run for each iteration of the loop + + - - - Executes a for loop in which iterations may run in parallel - - The number of concurrent execution threads to run - The loop will be started at this index - The loop will be terminated before this index is reached - Method body to run for each iteration of the loop + + - - - Executes a foreach loop in which iterations may run in parallel - - Object type that the collection wraps - An enumerable collection to iterate over - Method body to run for each object in the collection + + - - - Executes a foreach loop in which iterations may run in parallel - - Object type that the collection wraps - The number of concurrent execution threads to run - An enumerable collection to iterate over - Method body to run for each object in the collection + + - - - Executes a series of tasks in parallel - - A series of method bodies to execute + + - - - Executes a series of tasks in parallel - - The number of concurrent execution threads to run - A series of method bodies to execute + + - - - Exception class to identify inventory exceptions - + + - - - Responsible for maintaining inventory structure. Inventory constructs nodes - and manages node children as is necessary to maintain a coherant hirarchy. - Other classes should not manipulate or create InventoryNodes explicitly. When - A node's parent changes (when a folder is moved, for example) simply pass - Inventory the updated InventoryFolder and it will make the appropriate changes - to its internal representation. - + + - - The event subscribers, null of no subscribers + + - - Raises the InventoryObjectUpdated Event - A InventoryObjectUpdatedEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the InventoryObjectRemoved Event - A InventoryObjectRemovedEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the InventoryObjectAdded Event - A InventoryObjectAddedEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - - Returns the contents of the specified folder - - A folder's UUID - The contents of the folder corresponding to folder - When folder does not exist in the inventory + + - - - Updates the state of the InventoryNode and inventory data structure that - is responsible for the InventoryObject. If the item was previously not added to inventory, - it adds the item, and updates structure accordingly. If it was, it updates the - InventoryNode, changing the parent node if item.parentUUID does - not match node.Parent.Data.UUID. - - You can not set the inventory root folder using this method - - The InventoryObject to store + + - - - Removes the InventoryObject and all related node data from Inventory. - - The InventoryObject to remove. + + - - - Used to find out if Inventory contains the InventoryObject - specified by uuid. - - The UUID to check. - true if inventory contains uuid, false otherwise + + - - - Saves the current inventory structure to a cache file - - Name of the cache file to save to + + - - - Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful. - - Name of the cache file to load - The number of inventory items sucessfully reconstructed into the inventory node tree + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - - The root folder of this avatars inventory - + + - - - The default shared library folder - + + - - - The root node of the avatars inventory - + + - - - The root node of the default shared library - + + - - - By using the bracket operator on this class, the program can get the - InventoryObject designated by the specified uuid. If the value for the corresponding - UUID is null, the call is equivelant to a call to RemoveNodeFor(this[uuid]). - If the value is non-null, it is equivelant to a call to UpdateNodeFor(value), - the uuid parameter is ignored. - - The UUID of the InventoryObject to get or set, ignored if set to non-null value. - The InventoryObject corresponding to uuid. + + - - - The InternalDictionary class is used through the library for storing key/value pairs. - It is intended to be a replacement for the generic Dictionary class and should - be used in its place. It contains several methods for allowing access to the data from - outside the library that are read only and thread safe. - - - Key - Value + + - - Internal dictionary that this class wraps around. Do not - modify or enumerate the contents of this dictionary without locking - on this member + + - - - Initializes a new instance of the Class - with the specified key/value, has the default initial capacity. - - - - // initialize a new InternalDictionary named testDict with a string as the key and an int as the value. - public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(); - - + + - - - Initializes a new instance of the Class - with the specified key/value, has its initial valies copied from the specified - - - - to copy initial values from - - - // initialize a new InternalDictionary named testAvName with a UUID as the key and an string as the value. - // populates with copied values from example KeyNameCache Dictionary. - - // create source dictionary - Dictionary<UUID, string> KeyNameCache = new Dictionary<UUID, string>(); - KeyNameCache.Add("8300f94a-7970-7810-cf2c-fc9aa6cdda24", "Jack Avatar"); - KeyNameCache.Add("27ba1e40-13f7-0708-3e98-5819d780bd62", "Jill Avatar"); - - // Initialize new dictionary. - public InternalDictionary<UUID, string> testAvName = new InternalDictionary<UUID, string>(KeyNameCache); - - + + - - - Initializes a new instance of the Class - with the specified key/value, With its initial capacity specified. - - Initial size of dictionary - - - // initialize a new InternalDictionary named testDict with a string as the key and an int as the value, - // initially allocated room for 10 entries. - public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(10); - - + + - - - Try to get entry from with specified key - - Key to use for lookup - Value returned - if specified key exists, if not found - - - // find your avatar using the Simulator.ObjectsAvatars InternalDictionary: - Avatar av; - if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) - Console.WriteLine("Found Avatar {0}", av.Name); - - - + + - - - Finds the specified match. - - The match. - Matched value - - - // use a delegate to find a prim in the ObjectsPrimitives InternalDictionary - // with the ID 95683496 - uint findID = 95683496; - Primitive findPrim = sim.ObjectsPrimitives.Find( - delegate(Primitive prim) { return prim.ID == findID; }); - - + + - - Find All items in an - return matching items. - a containing found items. - - Find All prims within 20 meters and store them in a List - - int radius = 20; - List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( - delegate(Primitive prim) { - Vector3 pos = prim.Position; - return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); - } - ); - - + + - - Find All items in an - return matching keys. - a containing found keys. - - Find All keys which also exist in another dictionary - - List<UUID> matches = myDict.FindAll( - delegate(UUID id) { - return myOtherDict.ContainsKey(id); - } - ); - - + + - - Perform an on each entry in an - to perform - - - // Iterates over the ObjectsPrimitives InternalDictionary and prints out some information. - Client.Network.CurrentSim.ObjectsPrimitives.ForEach( - delegate(Primitive prim) - { - if (prim.Text != null) - { - Console.WriteLine("NAME={0} ID = {1} TEXT = '{2}'", - prim.PropertiesFamily.Name, prim.ID, prim.Text); - } - }); - - + + - - Perform an on each key of an - to perform + + - - - Perform an on each KeyValuePair of an - - to perform + + - - Check if Key exists in Dictionary - Key to check for - if found, otherwise + + - - Check if Value exists in Dictionary - Value to check for - if found, otherwise + + - - - Adds the specified key to the dictionary, dictionary locking is not performed, - - - The key - The value + + - - - Removes the specified key, dictionary locking is not performed - - The key. - if successful, otherwise + + - - - Gets the number of Key/Value pairs contained in the - + + - - - Indexer for the dictionary - - The key - The value + + - - - A Wrapper around openjpeg to encode and decode images to and from byte arrays - + + - - TGA Header size + + - - OpenJPEG is not threadsafe, so this object is used to lock - during calls into unmanaged code + + - - - Encode a object into a byte array - - The object to encode - true to enable lossless conversion, only useful for small images ie: sculptmaps - A byte array containing the encoded Image object + + - - - Encode a object into a byte array - - The object to encode - a byte array of the encoded image + + - - - Decode JPEG2000 data to an and - - - JPEG2000 encoded data - ManagedImage object to decode to - Image object to decode to - True if the decode succeeds, otherwise false + + - - - - - - - + + - - - - - - - - + + - - - Encode a object into a byte array - - The source object to encode - true to enable lossless decoding - A byte array containing the source Bitmap object + + - - - Defines the beginning and ending file positions of a layer in an - LRCP-progression JPEG2000 file - + + - - - This structure is used to marshal both encoded and decoded images. - MUST MATCH THE STRUCT IN dotnet.h! - + + - - - Information about a single packet in a JPEG2000 stream - + + - - Packet start position + + - - Packet header end position + + - - Packet end position + + - - - Image width - + + - - - Image height - + + - - - Image channel flags - + + - - - Red channel data - + + - - - Green channel data - + + - - - Blue channel data - + + - - - Alpha channel data - + + - - - Bump channel data - + + - - - Create a new blank image - - width - height - channel flags + + - - - - - + + - - - Convert the channels in the image. Channels are created or destroyed as required. - - new channel flags + + - - - Resize or stretch the image using nearest neighbor (ugly) resampling - - new width - new height + + - - - Create a byte array containing 32-bit RGBA data with a bottom-left - origin, suitable for feeding directly into OpenGL - - A byte array containing raw texture data + + - - - Create a byte array containing 32-bit RGBA data with a bottom-left - origin, suitable for feeding directly into OpenGL - - A byte array containing raw texture data + + - - - Represents a texture - + + - - A object containing image data + + - - + + - - + + - - Initializes a new instance of an AssetTexture object + + - - - Initializes a new instance of an AssetTexture object - - A unique specific to this asset - A byte array containing the raw asset data + + - - - Initializes a new instance of an AssetTexture object - - A object containing texture data + + - - - Populates the byte array with a JPEG2000 - encoded image created from the data in - + + - - - Decodes the JPEG2000 data in AssetData to the - object - - True if the decoding was successful, otherwise false + + - - - Decodes the begin and end byte positions for each quality layer in - the image - - + + - - Override the base classes AssetType + + - - - Operation to apply when applying color to texture - + + - - - Information needed to translate visual param value to RGBA color - + + - - - Construct VisualColorParam - - Operation to apply when applying color to texture - Colors + + - - - Represents alpha blending and bump infor for a visual parameter - such as sleive length - + + - - Stregth of the alpha to apply + + - - File containing the alpha channel + + - - Skip blending if parameter value is 0 + + - - Use miltiply insted of alpha blending + + - - - Create new alhpa information for a visual param - - Stregth of the alpha to apply - File containing the alpha channel - Skip blending if parameter value is 0 - Use miltiply insted of alpha blending + + - - - A single visual characteristic of an avatar mesh, such as eyebrow height - + + - - Index of this visual param + + - - Internal name + + - - Group ID this parameter belongs to + + - - Name of the wearable this parameter belongs to + + - - Displayable label of this characteristic + + - - Displayable label for the minimum value of this characteristic + + - - Displayable label for the maximum value of this characteristic + + - - Default value + + - - Minimum value + + - - Maximum value + + - - Is this param used for creation of bump layer? + + - - Alpha blending/bump info + + - - Color information + + - - Array of param IDs that are drivers for this parameter + + - - - Set all the values through the constructor - - Index of this visual param - Internal name - - - Displayable label of this characteristic - Displayable label for the minimum value of this characteristic - Displayable label for the maximum value of this characteristic - Default value - Minimum value - Maximum value - Is this param used for creation of bump layer? - Array of param IDs that are drivers for this parameter - Alpha blending/bump info - Color information + + - - - Holds the Params array of all the avatar appearance parameters - + + - - - Class for controlling various system settings. - - Some values are readonly because they affect things that - happen when the GridClient object is initialized, so changing them at - runtime won't do any good. Non-readonly values may affect things that - happen at login or dynamically + + - - Main grid login server + + - - Beta grid login server + + - - - InventoryManager requests inventory information on login, - GridClient initializes an Inventory store for main inventory. - + + - - - InventoryManager requests library information on login, - GridClient initializes an Inventory store for the library. - + + + + + - - Number of milliseconds between sending pings to each sim + + - - Number of milliseconds between sending camera updates + + - - Number of milliseconds between updating the current - positions of moving, non-accelerating and non-colliding objects + + - - Millisecond interval between ticks, where all ACKs are - sent out and the age of unACKed packets is checked + + - - The initial size of the packet inbox, where packets are - stored before processing + + - - Maximum size of packet that we want to send over the wire + + - - The maximum value of a packet sequence number before it - rolls over back to one + + - - The relative directory where external resources are kept + + - - Login server to connect to + + - - IP Address the client will bind to + + - - Use XML-RPC Login or LLSD Login, default is XML-RPC Login + + - - - Use Caps for fetching inventory where available - + + - - Number of milliseconds before an asset transfer will time - out + + - - Number of milliseconds before a teleport attempt will time - out + + - - Number of milliseconds before NetworkManager.Logout() will - time out + + - - Number of milliseconds before a CAPS call will time out - Setting this too low will cause web requests time out and - possibly retry repeatedly + + - - Number of milliseconds for xml-rpc to timeout + + - - Milliseconds before a packet is assumed lost and resent + + - - Milliseconds without receiving a packet before the - connection to a simulator is assumed lost + + - - Milliseconds to wait for a simulator info request through - the grid interface + + - - The maximum size of the sequence number archive, used to - check for resent and/or duplicate packets + + - - Maximum number of queued ACKs to be sent before SendAcks() - is forced + + - - Network stats queue length (seconds) + + - - - Primitives will be reused when falling in/out of interest list (and shared between clients) - prims returning to interest list do not need re-requested - Helps also in not re-requesting prim.Properties for code that checks for a Properties == null per client - + + - - - Pool parcel data between clients (saves on requesting multiple times when all clients may need it) - + + - - - How long to preserve cached data when no client is connected to a simulator - The reason for setting it to something like 2 minutes is in case a client - is running back and forth between region edges or a sim is comming and going - + + - - Enable/disable storing terrain heightmaps in the - TerrainManager + + - - Enable/disable sending periodic camera updates + + - - Enable/disable automatically setting agent appearance at - login and after sim crossing + + - - Enable/disable automatically setting the bandwidth throttle - after connecting to each simulator - The default throttle uses the equivalent of the maximum - bandwidth setting in the official client. If you do not set a - throttle your connection will by default be throttled well below - the minimum values and you may experience connection problems + + - - Enable/disable the sending of pings to monitor lag and - packet loss + + - - Should we connect to multiple sims? This will allow - viewing in to neighboring simulators and sim crossings - (Experimental) + + - - If true, all object update packets will be decoded in to - native objects. If false, only updates for our own agent will be - decoded. Registering an event handler will force objects for that - type to always be decoded. If this is disabled the object tracking - will have missing or partial prim and avatar information + + - - If true, when a cached object check is received from the - server the full object info will automatically be requested + + - - Whether to establish connections to HTTP capabilities - servers for simulators + + - - Whether to decode sim stats + + - - The capabilities servers are currently designed to - periodically return a 502 error which signals for the client to - re-establish a connection. Set this to true to log those 502 errors + + - - If true, any reference received for a folder or item - the library is not aware of will automatically be fetched + + - - If true, and SEND_AGENT_UPDATES is true, - AgentUpdate packets will continuously be sent out to give the bot - smoother movement and autopiloting + + - - If true, currently visible avatars will be stored - in dictionaries inside Simulator.ObjectAvatars. - If false, a new Avatar or Primitive object will be created - each time an object update packet is received + + - - If true, currently visible avatars will be stored - in dictionaries inside Simulator.ObjectPrimitives. - If false, a new Avatar or Primitive object will be created - each time an object update packet is received + + - - If true, position and velocity will periodically be - interpolated (extrapolated, technically) for objects and - avatars that are being tracked by the library. This is - necessary to increase the accuracy of speed and position - estimates for simulated objects + + - - - If true, utilization statistics will be tracked. There is a minor penalty - in CPU time for enabling this option. - + + - - If true, parcel details will be stored in the - Simulator.Parcels dictionary as they are received + + - - - If true, an incoming parcel properties reply will automatically send - a request for the parcel access list - + + - - - if true, an incoming parcel properties reply will automatically send - a request for the traffic count. - + + - - - If true, images, and other assets downloaded from the server - will be cached in a local directory - + + - - Path to store cached texture data + + - - Maximum size cached files are allowed to take on disk (bytes) + + - - Default color used for viewer particle effects + + - - Maximum number of times to resend a failed packet + + - - Throttle outgoing packet rate + + - - UUID of a texture used by some viewers to indentify type of client used + + - - - Download textures using GetTexture capability when available - + + - - The maximum number of concurrent texture downloads allowed - Increasing this number will not necessarily increase texture retrieval times due to - simulator throttles + + - - - The Refresh timer inteval is used to set the delay between checks for stalled texture downloads - - This is a static variable which applies to all instances + + - - - Textures taking longer than this value will be flagged as timed out and removed from the pipeline - + + - - - Get or set the minimum log level to output to the console by default - - If the library is not compiled with DEBUG defined and this level is set to DEBUG - You will get no output on the console. This behavior can be overriden by creating - a logger configuration file for log4net - + + - - Attach avatar names to log messages + + - - Log packet retransmission info + + - - Log disk cache misses and other info + + - - Constructor - Reference to a GridClient object + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Cost of uploading an asset - Read-only since this value is dynamically fetched at login + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + - - + + - - + + - - + + - - + + - - - - - - + + - - - - + + - - + + - - + + - - + + - - + + - - - - - - + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - - + + - - - - + + - - - - - - + + - - - - - - + + - - - - - + + - - Size of the byte array used to store raw packet data + + - - Raw packet data buffer + + - - Length of the data to transmit + + - - EndPoint of the remote host + + - - - Create an allocated UDP packet buffer for receiving a packet - + + - - - Create an allocated UDP packet buffer for sending a packet - - EndPoint of the remote host + + - - - Create an allocated UDP packet buffer for sending a packet - - EndPoint of the remote host - Size of the buffer to allocate for packet data + + - - - Object pool for packet buffers. This is used to allocate memory for all - incoming and outgoing packets, and zerocoding buffers for those packets - + + - - - Initialize the object pool in client mode - - Server to connect to - - + + - - - Initialize the object pool in server mode - - - + + - - - Returns a packet buffer with EndPoint set if the buffer is in - client mode, or with EndPoint set to null in server mode - - Initialized UDPPacketBuffer object + + - - - Default constructor - + + - - - Check a packet buffer out of the pool - - A packet buffer object + + - - - - + + - - OK + + - - Transfer completed + + - - + + - - + + - - Unknown error occurred + + - - Equivalent to a 404 error + + - - Client does not have permission for that resource + + - - Unknown status + + - - - - + + - - + + - - Unknown + + - - Virtually all asset transfers use this channel + + - - - - + + - - + + - - Asset from the asset server + + - - Inventory item + + - - Estate asset, such as an estate covenant + + - - - - + + - - + + - - + + - - + + - - - When requesting image download, type of the image requested - + + - - Normal in-world object texture + + - - Avatar texture + + - - Server baked avatar texture + + - - - Image file format - + + - - - - + + - - Number of milliseconds passed since the last transfer - packet was received + + - - - - + + - - - - + + + + + - - - - + + - - - - + + - - - - + + - - - - - - - - + + - - - - + + - - Number of milliseconds to wait for a transfer header packet if out of order data was received + + - - The event subscribers. null if no subcribers + + - - Raises the XferReceived event - A XferReceivedEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the AssetUploaded event - A AssetUploadedEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the UploadProgress event - A UploadProgressEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the InitiateDownload event - A InitiateDownloadEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the ImageReceiveProgress event - A ImageReceiveProgressEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - Texture download cache + + - - - Default constructor - - A reference to the GridClient object + + - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - The callback to fire when the simulator responds with the asset data + + - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - Source location of the requested asset - The callback to fire when the simulator responds with the asset data + + - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - Source location of the requested asset - UUID of the transaction - The callback to fire when the simulator responds with the asset data + + - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - Source location of the requested asset - UUID of the transaction - The callback to fire when the simulator responds with the asset data + + - - - Request an asset download through the almost deprecated Xfer system - - Filename of the asset to request - Whether or not to delete the asset - off the server after it is retrieved - Use large transfer packets or not - UUID of the file to request, if filename is - left empty - Asset type of vFileID, or - AssetType.Unknown if filename is not empty - Sets the FilePath in the request to Cache - (4) if true, otherwise Unknown (0) is used - + + - - - - - Use UUID.Zero if you do not have the - asset ID but have all the necessary permissions - The item ID of this asset in the inventory - Use UUID.Zero if you are not requesting an - asset from an object inventory - The owner of this asset - Asset type - Whether to prioritize this asset download or not - + + - - - Used to force asset data into the PendingUpload property, ie: for raw terrain uploads - - An AssetUpload object containing the data to upload to the simulator + + - - - Request an asset be uploaded to the simulator - - The Object containing the asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired + + - - - Request an asset be uploaded to the simulator - - The of the asset being uploaded - A byte array containing the encoded asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired + + - - - Request an asset be uploaded to the simulator - - - Asset type to upload this data as - A byte array containing the encoded asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired + + - - - Initiate an asset upload - - The ID this asset will have if the - upload succeeds - Asset type to upload this data as - Raw asset data to upload - Whether to store this asset on the local - simulator or the grid-wide asset server - The tranaction id for the upload - The transaction ID of this transfer + + - - - Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - A float indicating the requested priority for the transfer. Higher priority values tell the simulator - to prioritize the request before lower valued requests. An image already being transferred using the can have - its priority changed by resending the request with the new priority value - Number of quality layers to discard. - This controls the end marker of the data sent. Sending with value -1 combined with priority of 0 cancels an in-progress - transfer. - A bug exists in the Linden Simulator where a -1 will occasionally be sent with a non-zero priority - indicating an off-by-one error. - The packet number to begin the request at. A value of 0 begins the request - from the start of the asset texture - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request - - Request an image and fire a callback when the request is complete - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); - - private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", - asset.AssetID, - asset.AssetData.Length); - } - } - - Request an image and use an inline anonymous method to handle the downloaded texture data - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, delegate(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", - asset.AssetID, - asset.AssetData.Length); - } - } - ); - - Request a texture, decode the texture to a bitmap image and apply it to a imagebox - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); - - private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - ManagedImage imgData; - Image bitmap; - - if (state == TextureRequestState.Finished) - { - OpenJPEG.DecodeToImage(assetTexture.AssetData, out imgData, out bitmap); - picInsignia.Image = bitmap; - } - } - } - - + + - - - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data + + - - - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data + + - - - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request + + - - - Cancel a texture request - - The texture assets + + - - - Requests download of a mesh asset - - UUID of the mesh asset - Callback when the request completes + + - - - Fetach avatar texture on a grid capable of server side baking - - ID of the avatar - ID of the texture - Name of the part of the avatar texture applies to - Callback invoked on operation completion + + - - - Lets TexturePipeline class fire the progress event - - The texture ID currently being downloaded - the number of bytes transferred - the total number of bytes expected + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Raised when the simulator responds sends + + - - Raised during upload completes + + - - Raised during upload with progres update + + - - Fired when the simulator sends an InitiateDownloadPacket, used to download terrain .raw files + + - - Fired when a texture is in the process of being downloaded by the TexturePipeline class + + - - - Callback used for various asset download requests - - Transfer information - Downloaded asset, null on fail + + - - - Callback used upon competition of baked texture upload - - Asset UUID of the newly uploaded baked texture + + - - - A callback that fires upon the completition of the RequestMesh call - - Was the download successfull - Resulting mesh or null on problems + + - - Xfer data + + - - Upload data + + - - Filename used on the simulator + + - - Filename used by the client + + - - UUID of the image that is in progress + + - - Number of bytes received so far + + - - Image size in bytes + + - - Positional vector of the users position + + - - Velocity vector of the position + + - - At Orientation (X axis) of the position + + - - Up Orientation (Y axis) of the position + + - - Left Orientation (Z axis) of the position + + - - - Contains all mesh faces that belong to a prim - + + - - List of primitive faces + + - - - Decodes mesh asset into FacetedMesh - - Mesh primitive - Asset retrieved from the asset server - Level of detail - Resulting decoded FacetedMesh - True if mesh asset decoding was successful + + - - - Represents a string of characters encoded with specific formatting properties - + + - - A text string containing main text of the notecard + + - - List of s embedded on the notecard + + - - Construct an Asset of type Notecard + + - - - Construct an Asset object of type Notecard - - A unique specific to this asset - A byte array containing the raw asset data + + - - - Encode the raw contents of a string with the specific Linden Text properties - + + - - - Decode the raw asset data including the Linden Text properties - - true if the AssetData was successfully decoded + + - - Override the base classes AssetType + + - - - Represents an Animation - + + - - Default Constructor + + - - - Construct an Asset object of type Animation - - A unique specific to this asset - A byte array containing the raw asset data + + - - Override the base classes AssetType + + - - - - + + - - - An instance of DelegateWrapper which calls InvokeWrappedDelegate, - which in turn calls the DynamicInvoke method of the wrapped - delegate - + + - - - Callback used to call EndInvoke on the asynchronously - invoked DelegateWrapper - + + - - - Executes the specified delegate with the specified arguments - asynchronously on a thread pool thread - - - + + - - - Invokes the wrapped delegate synchronously - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - Calls EndInvoke on the wrapper and Close on the resulting WaitHandle - to prevent resource leaks - - + + - - - Delegate to wrap another delegate and its arguments - - - + + - - - - + + - - The event subscribers, null of no subscribers + + - - Raises the AttachedSound Event - A AttachedSoundEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the AttachedSoundGainChange Event - A AttachedSoundGainChangeEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the SoundTrigger Event - A SoundTriggerEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Raises the PreloadSound Event - A PreloadSoundEventArgs object containing - the data sent from the simulator + + - - Thread sync lock object + + - - - Construct a new instance of the SoundManager class, used for playing and receiving - sound assets - - A reference to the current GridClient instance + + - - - Plays a sound in the current region at full volume from avatar position - - UUID of the sound to be played + + - - - Plays a sound in the current region at full volume - - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. + + - - - Plays a sound in the current region - - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 + + - - - Plays a sound in the specified sim - - UUID of the sound to be played. - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 + + - - - Play a sound asset - - UUID of the sound to be played. - handle id for the sim to be played in. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Raised when the simulator sends us data containing - sound + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - Provides data for the event - The event occurs when the simulator sends - the sound data which emits from an agents attachment - - The following code example shows the process to subscribe to the event - and a stub to handle the data passed from the simulator - - // Subscribe to the AttachedSound event - Client.Sound.AttachedSound += Sound_AttachedSound; - - // process the data raised in the event here - private void Sound_AttachedSound(object sender, AttachedSoundEventArgs e) - { - // ... Process AttachedSoundEventArgs here ... - } - - + + - - - Construct a new instance of the SoundTriggerEventArgs class - - Simulator where the event originated - The sound asset id - The ID of the owner - The ID of the object - The volume level - The + + - - Simulator where the event originated + + - - Get the sound asset id + + - - Get the ID of the owner + + - - Get the ID of the Object + + - - Get the volume level + + - - Get the + + - - Provides data for the event - The event occurs when an attached sound - changes its volume level + + - - - Construct a new instance of the AttachedSoundGainChangedEventArgs class - - Simulator where the event originated - The ID of the Object - The new volume level + + - - Simulator where the event originated + + - - Get the ID of the Object + + - - Get the volume level + + - - Provides data for the event - The event occurs when the simulator forwards - a request made by yourself or another agent to play either an asset sound or a built in sound - - Requests to play sounds where the is not one of the built-in - will require sending a request to download the sound asset before it can be played - - - The following code example uses the , - and - properties to display some information on a sound request on the window. - - // subscribe to the event - Client.Sound.SoundTrigger += Sound_SoundTrigger; - - // play the pre-defined BELL_TING sound - Client.Sound.SendSoundTrigger(Sounds.BELL_TING); - - // handle the response data - private void Sound_SoundTrigger(object sender, SoundTriggerEventArgs e) - { - Console.WriteLine("{0} played the sound {1} at volume {2}", - e.OwnerID, e.SoundID, e.Gain); - } - - + + - - - Construct a new instance of the SoundTriggerEventArgs class - - Simulator where the event originated - The sound asset id - The ID of the owner - The ID of the object - The ID of the objects parent - The volume level - The regionhandle - The source position + + - - Simulator where the event originated + + - - Get the sound asset id + + - - Get the ID of the owner + + - - Get the ID of the Object + + - - Get the ID of the objects parent + + - - Get the volume level + + - - Get the regionhandle + + - - Get the source position + + - - Provides data for the event - The event occurs when the simulator sends - the appearance data for an avatar - - The following code example uses the and - properties to display the selected shape of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; - - // handle the data when the event is raised - void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) - { - Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") - } - - + + - - - Construct a new instance of the PreloadSoundEventArgs class - - Simulator where the event originated - The sound asset id - The ID of the owner - The ID of the object + + + + + + + + - - Simulator where the event originated + + - - Get the sound asset id + + - - Get the ID of the owner + + - - Get the ID of the Object + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - Status of the last application run. - Used for error reporting to the grid login service for statistical purposes. - + + - - Application exited normally + + - - Application froze + + - - Application detected error and exited abnormally + + - - Other crash + + - - Application froze during logout + + - - Application crashed during logout + + - - - Login Request Parameters - + + - - The URL of the Login Server + + - - The number of milliseconds to wait before a login is considered - failed due to timeout + + - - The request method - login_to_simulator is currently the only supported method + + - - The Agents First name + + - - The Agents Last name + + - - A md5 hashed password - plaintext password will be automatically hashed + + - - The agents starting location once logged in - Either "last", "home", or a string encoded URI - containing the simulator name and x/y/z coordinates e.g: uri:hooper&128&152&17 + + - - A string containing the client software channel information - Second Life Release + + - - The client software version information - The official viewer uses: Second Life Release n.n.n.n - where n is replaced with the current version of the viewer + + - - A string containing the platform information the agent is running on + + - - A string hash of the network cards Mac Address + + - - Unknown or deprecated + + - - A string hash of the first disk drives ID used to identify this clients uniqueness + + - - A string containing the viewers Software, this is not directly sent to the login server but - instead is used to generate the Version string + + - - A string representing the software creator. This is not directly sent to the login server but - is used by the library to generate the Version information + + - - If true, this agent agrees to the Terms of Service of the grid its connecting to + + - - Unknown + + - - Status of the last application run sent to the grid login server for statistical purposes + + - - An array of string sent to the login server to enable various options + + - - A randomly generated ID to distinguish between login attempts. This value is only used - internally in the library and is never sent over the wire + + - - - Default constuctor, initializes sane default values - + + - - - Instantiates new LoginParams object and fills in the values - - Instance of GridClient to read settings from - Login first name - Login last name - Password - Login channnel (application name) - Client version, should be application name + version number + + - - - Instantiates new LoginParams object and fills in the values - - Instance of GridClient to read settings from - Login first name - Login last name - Password - Login channnel (application name) - Client version, should be application name + version number - URI of the login server + + - - - The decoded data returned from the login server after a successful login - + + - - true, false, indeterminate + + - - Login message of the day + + - - M or PG, also agent_region_access and agent_access_max + + - - - Parse LLSD Login Reply Data - - An - contaning the login response data - XML-RPC logins do not require this as XML-RPC.NET - automatically populates the struct properly using attributes + + - - - Static pre-defined animations available to all agents - + + - - Agent with afraid expression on face + + - - Agent aiming a bazooka (right handed) + + - - Agent aiming a bow (left handed) + + - - Agent aiming a hand gun (right handed) + + - - Agent aiming a rifle (right handed) + + - - Agent with angry expression on face + + - - Agent hunched over (away) + + - - Agent doing a backflip + + - - Agent laughing while holding belly + + - - Agent blowing a kiss + + - - Agent with bored expression on face + + - - Agent bowing to audience + + - - Agent brushing himself/herself off + + - - Agent in busy mode + + - - Agent clapping hands + + - - Agent doing a curtsey bow + + - - Agent crouching + + - - Agent crouching while walking + + - - Agent crying + + - - Agent unanimated with arms out (e.g. setting appearance) + + - - Agent re-animated after set appearance finished + + - - Agent dancing + + - - Agent dancing + + - - Agent dancing + + - - Agent dancing + + - - Agent dancing + + - - Agent dancing + + - - Agent dancing + + - - Agent dancing + + - - Agent on ground unanimated + + - - Agent boozing it up + + - - Agent with embarassed expression on face + + - - Agent with afraid expression on face + + - - Agent with angry expression on face + + - - Agent with bored expression on face + + - - Agent crying + + - - Agent showing disdain (dislike) for something + + - - Agent with embarassed expression on face + + - - Agent with frowning expression on face + + - - Agent with kissy face + + - - Agent expressing laughgter + + - - Agent with open mouth + + - - Agent with repulsed expression on face + + - - Agent expressing sadness + + - - Agent shrugging shoulders + + - - Agent with a smile + + - - Agent expressing surprise + + - - Agent sticking tongue out + + - - Agent with big toothy smile + + - - Agent winking + + - - Agent expressing worry + + - - Agent falling down + + + + + + + + + + + + + + + + + + + + + + + - - Agent walking (feminine version) + + - - Agent wagging finger (disapproval) + + - - I'm not sure I want to know + + - - Agent in superman position + + - - Agent in superman position + + - - Agent greeting another + + - - Agent holding bazooka (right handed) + + - - Agent holding a bow (left handed) + + - - Agent holding a handgun (right handed) + + - - Agent holding a rifle (right handed) + + - - Agent throwing an object (right handed) + + - - Agent in static hover + + - - Agent hovering downward + + - - Agent hovering upward + + - - Agent being impatient + + - - Agent jumping + + - - Agent jumping with fervor + + - - Agent point to lips then rear end + + - - Agent landing from jump, finished flight, etc + + - - Agent laughing + + - - Agent landing from jump, finished flight, etc + + - - Agent sitting on a motorcycle + + - - + + - - Agent moving head side to side + + - - Agent moving head side to side with unhappy expression + + - - Agent taunting another + + - - + + - - Agent giving peace sign + + - - Agent pointing at self + + - - Agent pointing at another + + - - Agent preparing for jump (bending knees) + + - - Agent punching with left hand + + - - Agent punching with right hand + + - - Agent acting repulsed + + - - Agent trying to be Chuck Norris + + - - Rocks, Paper, Scissors 1, 2, 3 + + - - Agent with hand flat over other hand + + - - Agent with fist over other hand + + - - Agent with two fingers spread over other hand + + - - Agent running + + - - Agent appearing sad + + - - Agent saluting + + - - Agent shooting bow (left handed) + + - - Agent cupping mouth as if shouting + + - - Agent shrugging shoulders + + - - Agent in sit position + + - - Agent in sit position (feminine) + + - - Agent in sit position (generic) + + - - Agent sitting on ground + + - - Agent sitting on ground + + - - + + - - Agent sleeping on side + + - - Agent smoking + + - - Agent inhaling smoke + + - - + + - - Agent taking a picture + + - - Agent standing + + - - Agent standing up + + - - Agent standing + + - - Agent standing + + - - Agent standing + + - - Agent standing + + - - Agent stretching + + - - Agent in stride (fast walk) + + - - Agent surfing + + - - Agent acting surprised + + - - Agent striking with a sword + + - - Agent talking (lips moving) + + - - Agent throwing a tantrum + + - - Agent throwing an object (right handed) + + - - Agent trying on a shirt + + - - Agent turning to the left + + - - Agent turning to the right + + - - Agent typing + + - - Agent walking + + - - Agent whispering + + - - Agent whispering with fingers in mouth + + - - Agent winking + + - - Agent winking + + - - Agent worried + + - - Agent nodding yes + + - - Agent nodding yes with happy face + + - - Agent floating with legs and arms crossed + + - - - A dictionary containing all pre-defined animations - - A dictionary containing the pre-defined animations, - where the key is the animations ID, and the value is a string - containing a name to identify the purpose of the animation + + - - - A linkset asset, containing a parent primitive and zero or more children - + + - - Initializes a new instance of an AssetPrim object + + - - - Initializes a new instance of an AssetPrim object - - A unique specific to this asset - A byte array containing the raw asset data + + - - - - + + - - - - - + + - - Override the base classes AssetType + + - - - Only used internally for XML serialization/deserialization - + + - - - The deserialized form of a single primitive in a linkset asset - + + - - - - - Looking direction, must be a normalized vector - Up direction, must be a normalized vector + + - - - Align the coordinate frame X and Y axis with a given rotation - around the Z axis in radians - - Absolute rotation around the Z axis in - radians + + - - Origin position of this coordinate frame + + - - X axis of this coordinate frame, or Forward/At in grid terms + + - - Y axis of this coordinate frame, or Left in grid terms + + - - Z axis of this coordinate frame, or Up in grid terms + + - - - - + + - - The avatar has no rights + + - - The avatar can see the online status of the target avatar + + - - The avatar can see the location of the target avatar on the map + + - - The avatar can modify the ojects of the target avatar + + - - - This class holds information about an avatar in the friends list. There are two ways - to interface to this class. The first is through the set of boolean properties. This is the typical - way clients of this class will use it. The second interface is through two bitflag properties, - TheirFriendsRights and MyFriendsRights - + + - - - Used internally when building the initial list of friends at login time - - System ID of the avatar being prepesented - Rights the friend has to see you online and to modify your objects - Rights you have to see your friend online and to modify their objects + + - - - FriendInfo represented as a string - - A string reprentation of both my rights and my friends rights + + - - - System ID of the avatar - + + - - - full name of the avatar - + + - - - True if the avatar is online - + + - - - True if the friend can see if I am online - + + - - - True if the friend can see me on the map - + + - - - True if the freind can modify my objects - + + - - - True if I can see if my friend is online - + + - - - True if I can see if my friend is on the map - + + - - - True if I can modify my friend's objects - + + - - - My friend's rights represented as bitmapped flags - + + - - - My rights represented as bitmapped flags - + + - - - This class is used to add and remove avatars from your friends list and to manage their permission. - + + - - The event subscribers. null if no subcribers + + - - Raises the FriendOnline event - A FriendInfoEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendOffline event - A FriendInfoEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendRightsUpdate event - A FriendInfoEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendNames event - A FriendNamesEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendshipOffered event - A FriendshipOfferedEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendshipResponse event - A FriendshipResponseEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendshipTerminated event - A FriendshipTerminatedEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendFoundReply event - A FriendFoundReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - - A dictionary of key/value pairs containing known friends of this avatar. - - The Key is the of the friend, the value is a - object that contains detailed information including permissions you have and have given to the friend - + + - - - A Dictionary of key/value pairs containing current pending frienship offers. - - The key is the of the avatar making the request, - the value is the of the request which is used to accept - or decline the friendship offer - + + - - - Internal constructor - - A reference to the GridClient Object + + - - - Accept a friendship request - - agentID of avatatar to form friendship with - imSessionID of the friendship request message + + - - - Decline a friendship request - - of friend - imSessionID of the friendship request message + + - - - Overload: Offer friendship to an avatar. - - System ID of the avatar you are offering friendship to + + - - - Offer friendship to an avatar. - - System ID of the avatar you are offering friendship to - A message to send with the request + + - - - Terminate a friendship with an avatar - - System ID of the avatar you are terminating the friendship with + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - - Change the rights of a friend avatar. - - the of the friend - the new rights to give the friend - This method will implicitly set the rights to those passed in the rights parameter. + + - - - Use to map a friends location on the grid. - - Friends UUID to find - + + - - - Use to track a friends movement on the grid - - Friends Key + + - - - Ask for a notification of friend's online status - - Friend's UUID + + - - - This handles the asynchronous response of a RequestAvatarNames call. - - - names cooresponding to the the list of IDs sent the the RequestAvatarNames call. + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - - Populate FriendList with data from the login reply - - true if login was successful - true if login request is requiring a redirect - A string containing the response to the login request - A string containing the reason for the request - A object containing the decoded - reply from the login server + + - - Raised when the simulator sends notification one of the members in our friends list comes online + + - - Raised when the simulator sends notification one of the members in our friends list goes offline + + - - Raised when the simulator sends notification one of the members in our friends list grants or revokes permissions + + - - Raised when the simulator sends us the names on our friends list + + - - Raised when the simulator sends notification another agent is offering us friendship + + - - Raised when a request we sent to friend another agent is accepted or declined + + - - Raised when the simulator sends notification one of the members in our friends list has terminated - our friendship + + - - Raised when the simulator sends the location of a friend we have - requested map location info for + + - - Contains information on a member of our friends list + + - - - Construct a new instance of the FriendInfoEventArgs class - - The FriendInfo + + - - Get the FriendInfo + + - - Contains Friend Names + + - - - Construct a new instance of the FriendNamesEventArgs class - - A dictionary where the Key is the ID of the Agent, - and the Value is a string containing their name + + + + + + + + - - A dictionary where the Key is the ID of the Agent, - and the Value is a string containing their name + + - - Sent when another agent requests a friendship with our agent + + - - - Construct a new instance of the FriendshipOfferedEventArgs class - - The ID of the agent requesting friendship - The name of the agent requesting friendship - The ID of the session, used in accepting or declining the - friendship offer + + - - Get the ID of the agent requesting friendship + + - - Get the name of the agent requesting friendship + + - - Get the ID of the session, used in accepting or declining the - friendship offer + + - - A response containing the results of our request to form a friendship with another agent + + - - - Construct a new instance of the FriendShipResponseEventArgs class - - The ID of the agent we requested a friendship with - The name of the agent we requested a friendship with - true if the agent accepted our friendship offer + + - - Get the ID of the agent we requested a friendship with + + - - Get the name of the agent we requested a friendship with + + - - true if the agent accepted our friendship offer + + - - Contains data sent when a friend terminates a friendship with us + + - - - Construct a new instance of the FrindshipTerminatedEventArgs class - - The ID of the friend who terminated the friendship with us - The name of the friend who terminated the friendship with us + + - - Get the ID of the agent that terminated the friendship with us + + - - Get the name of the agent that terminated the friendship with us + + - - - Data sent in response to a request which contains the information to allow us to map the friends location - + + - - - Construct a new instance of the FriendFoundReplyEventArgs class - - The ID of the agent we have requested location information for - The region handle where our friend is located - The simulator local position our friend is located + + - - Get the ID of the agent we have received location information for + + - - Get the region handle where our mapped friend is located + + - - Get the simulator local position where our friend is located + + - - - Avatar profile flags - + + - - - Represents an avatar (other than your own) - + + - - Groups that this avatar is a member of + + - - Positive and negative ratings + + - - Avatar properties including about text, profile URL, image IDs and - publishing settings + + - - Avatar interests including spoken languages, skills, and "want to" - choices + + - - Movement control flags for avatars. Typically not set or used by - clients. To move your avatar, use Client.Self.Movement instead + + - - - Contains the visual parameters describing the deformation of the avatar - + + - - - Appearance version. Value greater than 0 indicates using server side baking - + + - - - Version of the Current Outfit Folder that the appearance is based on - + + - - - Appearance flags. Introduced with server side baking, currently unused. - + + - - - List of current avatar animations - + + - - - Default constructor - + + - - First name + + - - Last name + + - - Full name + + - - Active group + + - - - Positive and negative ratings - + + - - Positive ratings for Behavior + + - - Negative ratings for Behavior + + - - Positive ratings for Appearance + + - - Negative ratings for Appearance + + - - Positive ratings for Building + + - - Negative ratings for Building + + - - Positive ratings given by this avatar + + - - Negative ratings given by this avatar + + - - - Avatar properties including about text, profile URL, image IDs and - publishing settings - + + - - First Life about text + + - - First Life image ID + + - - + + - - + + - - + + - - + + - - Profile image ID + + - - Flags of the profile + + - - Web URL for this profile + + - - Should this profile be published on the web + + - - Avatar Online Status + + - - Is this a mature profile + + - - + + - - + + - - - Avatar interests including spoken languages, skills, and "want to" - choices - + + - - Languages profile field + + - - + + - - + + - - + + - - + + - - - Level of Detail mesh - + + - - - Represents an Animation - + + - - Default Constructor + + - - - Construct an Asset object of type Animation - - Asset type - A unique specific to this asset - A byte array containing the raw asset data + + - - Override the base classes AssetType + + - - The event subscribers. null if no subcribers + + - - Raises the LandPatchReceived event - A LandPatchReceivedEventArgs object containing the - data returned from the simulator + + - - Thread sync lock object + + - - - Default constructor - - + + - - Raised when the simulator responds sends + + - - Simulator from that sent tha data + + - - Sim coordinate of the patch + + - - Sim coordinate of the patch + + - - Size of tha patch + + - - Heightmap for the patch + + - - - Registers, unregisters, and fires events generated by incoming packets - + + - - Reference to the GridClient object + + - - - Default constructor - - + + - - - Register an event handler - - Use PacketType.Default to fire this event on every - incoming packet - Packet type to register the handler for - Callback to be fired - True if this callback should be ran - asynchronously, false to run it synchronous + + - - - Unregister an event handler - - Packet type to unregister the handler for - Callback to be unregistered + + - - - Fire the events registered for this packet type - - Incoming packet type - Incoming packet - Simulator this packet was received from + + - - - Object that is passed to worker threads in the ThreadPool for - firing packet callbacks - + + - - Callback to fire for this packet + + - - Reference to the simulator that this packet came from + + - - The packet that needs to be processed + + - - - Registers, unregisters, and fires events generated by the Capabilities - event queue - + + - - Reference to the GridClient object + + - - - Default constructor - - Reference to the GridClient object + + - - - Register an new event handler for a capabilities event sent via the EventQueue - - Use String.Empty to fire this event on every CAPS event - Capability event name to register the - handler for - Callback to fire + + - - - Unregister a previously registered capabilities handler - - Capability event name unregister the - handler for - Callback to unregister + + - - - Fire the events registered for this event type synchronously - - Capability name - Decoded event body - Reference to the simulator that - generated this event + + - - - Fire the events registered for this event type asynchronously - - Capability name - Decoded event body - Reference to the simulator that - generated this event + + - - - Object that is passed to worker threads in the ThreadPool for - firing CAPS callbacks - + + - - Callback to fire for this packet + + - - Name of the CAPS event + + - - Strongly typed decoded data + + - - Reference to the simulator that generated this event + + - - - Represents an LSL Text object containing a string of UTF encoded characters - + + - - A string of characters represting the script contents + + - - Initializes a new AssetScriptText object + + - - - Initializes a new AssetScriptText object with parameters - - A unique specific to this asset - A byte array containing the raw asset data + + - - - Encode a string containing the scripts contents into byte encoded AssetData - + + - - - Decode a byte array containing the scripts contents into a string - - true if decoding is successful + + - - Override the base classes AssetType + + - - - - + + - - + + - - + + - - + + - - - Thrown when a packet could not be successfully deserialized - + + - - - Default constructor - + + - - - Constructor that takes an additional error message - - An error message to attach to this exception + + - - - The header of a message template packet. Holds packet flags, sequence - number, packet ID, and any ACKs that will be appended at the end of - the packet - + + - - - Convert the AckList to a byte array, used for packet serializing - - Reference to the target byte array - Beginning position to start writing to in the byte - array, will be updated with the ending position of the ACK list + + - - - - - - - - + + - - - - - - - + + - - - A block of data in a packet. Packets are composed of one or more blocks, - each block containing one or more fields - + + - - - Create a block from a byte array - - Byte array containing the serialized block - Starting position of the block in the byte array. - This will point to the data after the end of the block when the - call returns + + - - - Serialize this block into a byte array - - Byte array to serialize this block into - Starting position in the byte array to serialize to. - This will point to the position directly after the end of the - serialized block when the call returns + + - - Current length of the data in this packet + + - - A generic value, not an actual packet type + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + Parsing Collada model files into data structures + - - + + + Parses Collada document + + Load .dae model from this file + Load and decode images for uploading with model + A list of mesh prims that were parsed from the collada file - - + + + Implements mesh upload communications with the simulator + - - + + + Inlcude stub convex hull physics, required for uploading to Second Life + - - + + + Use the same mesh used for geometry as the physical mesh upload + - - + + + Creates instance of the mesh uploader + + GridClient instance to communicate with the simulator + List of ModelPrimitive objects to upload as a linkset + Inventory name for newly uploaded object + Inventory description for newly upload object - - + + + Performs model upload in one go, without first checking for the price + - - + + + Performs model upload in one go, without first checking for the price + + Callback that will be invoke upon completion of the upload. Null is sent on request failure - - + + + Ask server for details of cost and impact of the mesh upload + + Callback that will be invoke upon completion of the upload. Null is sent on request failure - - + + + Performas actual mesh and image upload + + Uri recieved in the upload prepare stage + Callback that will be invoke upon completion of the upload. Null is sent on request failure - - + + + Callback for mesh upload operations + + null on failure, result from server on success - - + + + Interface requirements for Messaging system + - - + + + Abstract base for rendering plugins + - - + + + Generates a basic mesh structure from a primitive + + Primitive to generate the mesh from + Level of detail to generate the mesh at + The generated mesh - - + + + Generates a basic mesh structure from a sculpted primitive and + texture + + Sculpted primitive to generate the mesh from + Sculpt texture + Level of detail to generate the mesh at + The generated mesh - - + + + Generates a series of faces, each face containing a mesh and + metadata + + Primitive to generate the mesh from + Level of detail to generate the mesh at + The generated mesh - - + + + Generates a series of faces for a sculpted prim, each face + containing a mesh and metadata + + Sculpted primitive to generate the mesh from + Sculpt texture + Level of detail to generate the mesh at + The generated mesh - - + + + Apply texture coordinate modifications from a + to a list of vertices + + Vertex list to modify texture coordinates for + Center-point of the face + Face texture parameters + Scale of the prim - - + + + Sent to the client to indicate a teleport request has completed + - - + + The of the agent - - + + - - + + The simulators handle the agent teleported to - - + + A Uri which contains a list of Capabilities the simulator supports - - + + Indicates the level of access required + to access the simulator, or the content rating, or the simulators + map status - - + + The IP Address of the simulator - - + + The UDP Port the simulator will listen for UDP traffic on - - + + Status flags indicating the state of the Agent upon arrival, Flying, etc. - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Sent to the viewer when a neighboring simulator is requesting the agent make a connection to it. + - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + A message sent to the client which indicates a teleport request has failed + and contains some information on why it failed + - - + + - - + + A string key of the reason the teleport failed e.g. CouldntTPCloser + Which could be used to look up a value in a dictionary or enum - - + + The of the Agent - - + + A string human readable message containing the reason + An example: Could not teleport closer to destination - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Contains a list of prim owner information for a specific parcel in a simulator + + + A Simulator will always return at least 1 entry + If agent does not have proper permission the OwnerID will be UUID.Zero + If agent does not have proper permission OR there are no primitives on parcel + the DataBlocksExtended map will not be sent from the simulator + - - + + An Array of objects - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Prim ownership information for a specified owner on a single parcel + - - + + The of the prim owner, + UUID.Zero if agent has no permission to view prim owner information - - + + The total number of prims - - + + True if the OwnerID is a - - + + True if the owner is online + This is no longer used by the LL Simulators - - + + The date the most recent prim was rezzed - - + + + The details of a single parcel in a region, also contains some regionwide globals + - - + + Simulator-local ID of this parcel - - + + Maximum corner of the axis-aligned bounding box for this + parcel - - + + Minimum corner of the axis-aligned bounding box for this + parcel - - + + Total parcel land area - - + + - - + + Key of authorized buyer - - + + Bitmap describing land layout in 4x4m squares across the + entire region - - + + - - + + Date land was claimed - - + + Appears to always be zero - - + + Parcel Description - - + + - - + + - - + + Total number of primitives owned by the parcel group on + this parcel - - + + Whether the land is deeded to a group or not - - + + - - + + Maximum number of primitives this parcel supports - - + + The Asset UUID of the Texture which when applied to a + primitive will display the media - - + + A URL which points to any Quicktime supported media type - - + + A byte, if 0x1 viewer should auto scale media to fit object - - + + URL For Music Stream - - + + Parcel Name - - + + Autoreturn value in minutes for others' objects - - + + - - + + Total number of other primitives on this parcel - - + + UUID of the owner of this parcel - - + + Total number of primitives owned by the parcel owner on + this parcel - - + + - - + + How long is pass valid for - - + + Price for a temporary pass - - + + - - + + Disallows people outside the parcel from being able to see in - - + + - - + + - - + + - - + + True if the region denies access to age unverified users - - + + - - + + This field is no longer used - - + + The result of a request for parcel properties - - + + Sale price of the parcel, only useful if ForSale is set + The SalePrice will remain the same after an ownership + transfer (sale), so it can be used to see the purchase price after + a sale if the new owner has not changed it - - + + + Number of primitives your avatar is currently + selecting and sitting on in this parcel + - - + + - - + + + A number which increments by 1, starting at 0 for each ParcelProperties request. + Can be overriden by specifying the sequenceID with the ParcelPropertiesRequest being sent. + a Negative number indicates the action in has occurred. + - - + + Maximum primitives across the entire simulator - - + + Total primitives across the entire simulator - - + + - - + + Key of parcel snapshot - - + + Parcel ownership status - - + + Total number of primitives on this parcel - - + + - - + + - - + + A description of the media - - + + An Integer which represents the height of the media - - + + An integer which represents the width of the media - - + + A boolean, if true the viewer should loop the media - - + + A string which contains the mime type of the media - - + + true to obscure (hide) media url - - + + true to obscure (hide) music url - - + + true if avatars in this parcel should be invisible to people outside - - + + true if avatars outside can hear any sounds avatars inside play - - + + true if group members outside can hear any sounds avatars inside play - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + A message sent from the viewer to the simulator to updated a specific parcels settings - - + + The of the agent authorized to purchase this + parcel of land or a NULL if the sale is authorized to anyone - - + + true to enable auto scaling of the parcel media - - + + The category of this parcel used when search is enabled to restrict + search results - - + + A string containing the description to set - - + + The of the which allows for additional + powers and restrictions. - - + + The which specifies how avatars which teleport + to this parcel are handled - - + + The LocalID of the parcel to update settings on - - + + A string containing the description of the media which can be played + to visitors - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + true if avatars in this parcel should be invisible to people outside - - + + true if avatars outside can hear any sounds avatars inside play - - + + true if group members outside can hear any sounds avatars inside play - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + Base class used for the RemoteParcelRequest message - - + + + A message sent from the viewer to the simulator to request information + on a remote parcel + - - + + Local sim position of the parcel we are looking up - - + + Region handle of the parcel we are looking up - - + + Region of the parcel we are looking up - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + A message sent from the simulator to the viewer in response to a + which will contain parcel information + - - + + The grid-wide unique parcel ID - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + A message containing a request for a remote parcel from a viewer, or a response + from the simulator to that request + - - + + The request or response details block - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + A message sent from the simulator to an agent which contains + the groups the agent is in + - - + + The Agent receiving the message - - + + An array containing information + for each the agent is a member of - - + + An array containing information + for each the agent is a member of - - + + + Serialize the object + + An containing the objects data - + - pre-defined built in sounds + Deserialize the message + An containing the data - - + + Group Details specific to the agent - - + + true of the agent accepts group notices - - + + The agents tier contribution to the group - - + + The Groups - - + + The of the groups insignia - - + + The name of the group - - + + The aggregate permissions the agent has in the group for all roles the agent + is assigned - - + + An optional block containing additional agent specific information - - coins + + true of the agent allows this group to be + listed in their profile - - cash register bell + + + A message sent from the viewer to the simulator which + specifies the language and permissions for others to detect + the language specified + - - + + A string containng the default language + to use for the agent - - + + true of others are allowed to + know the language setting - - rubber + + + Serialize the object + + An containing the objects data - - plastic + + + Deserialize the message + + An containing the data - - flesh + + + An EventQueue message sent from the simulator to an agent when the agent + leaves a group + - - wood splintering? + + + An Array containing the AgentID and GroupID + + + + + Serialize the object + + An containing the objects data - - glass break + + + Deserialize the message + + An containing the data - - metal clunk + + An object containing the Agents UUID, and the Groups UUID - - whoosh + + The ID of the Agent leaving the group - - shake + + The GroupID the Agent is leaving - - + + Base class for Asset uploads/results via Capabilities - - ding + + + The request state + - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + A message sent from the viewer to the simulator to request a temporary upload capability + which allows an asset to be uploaded + - - + + The Capability URL sent by the simulator to upload the baked texture to - - + + + A message sent from the simulator that will inform the agent the upload is complete, + and the UUID of the uploaded asset + - - + + The uploaded texture asset ID - - + + + A message sent from the viewer to the simulator to request a temporary + capability URI which is used to upload an agents baked appearance textures + - - + + Object containing request or response - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + A message sent from the simulator which indicates the minimum version required for + using voice chat + - - + + Major Version Required - - + + Minor version required - - + + The name of the region sending the version requrements - + - A dictionary containing all pre-defined sounds + Serialize the object - A dictionary containing the pre-defined sounds, - where the key is the sounds ID, and the value is a string - containing a name to identify the purpose of the sound + An containing the objects data - + - + Deserialize the message + An containing the data - + - + A message sent from the simulator to the viewer containing the + voice server URI - - - - De-serialization constructor for the InventoryNode Class - + + The Parcel ID which the voice server URI applies - + + The name of the region + + + A uri containing the server/channel information + which the viewer can utilize to participate in voice conversations + + - Serialization handler for the InventoryNode Class + Serialize the object + An containing the objects data - + - De-serialization handler for the InventoryNode Class + Deserialize the message + An containing the data - + - - - - - - - User data - - - - + - + - + - For inventory folder nodes specifies weather the folder needs to be - refreshed from the server + Serialize the object + An containing the objects data - + - Represends individual HTTP Download request + Deserialize the message + An containing the data - - URI of the item to fetch - - - Timout specified in milliseconds - - - Download progress callback - - - Download completed callback - - - Accept the following content type - - - How many times will this request be retried - - - Current fetch attempt + + + A message sent by the viewer to the simulator to request a temporary + capability for a script contained with in a Tasks inventory to be updated + - - Default constructor + + Object containing request or response - - Constructor + + + Serialize the object + + An containing the objects data - + - Manages async HTTP downloads with a limit on maximum - concurrent downloads + Deserialize the message + An containing the data - - Default constructor + + + A message sent from the simulator to the viewer to indicate + a Tasks scripts status. + - - Cleanup method + + The Asset ID of the script - - Setup http download request + + True of the script is compiled/ran using the mono interpreter, false indicates it + uses the older less efficient lsl2 interprter - - Check the queue for pending work + + The Task containing the scripts - - Enqueue a new HTPP download + + true of the script is in a running state - - Maximum number of parallel downloads from a single endpoint + + + Serialize the object + + An containing the objects data - - Client certificate + + + Deserialize the message + + An containing the data - + - Capabilities is the name of the bi-directional HTTP REST protocol - used to communicate non real-time transactions such as teleporting or - group messaging + A message containing the request/response used for updating a gesture + contained with an agents inventory - - Reference to the simulator this system is connected to + + Object containing request or response - + - Default constructor + Serialize the object - - + An containing the objects data - + - Request the URI of a named capability + Deserialize the message - Name of the capability to request - The URI of the requested capability, or String.Empty if - the capability does not exist + An containing the data - + - Process any incoming events, check to see if we have a message created for the event, + A message request/response which is used to update a notecard contained within + a tasks inventory - - - - Capabilities URI this system was initialized with + + The of the Task containing the notecard asset to update - - Whether the capabilities event queue is connected and - listening for incoming events + + The notecard assets contained in the tasks inventory - + - Triggered when an event is received via the EventQueueGet - capability + Serialize the object - Event name - Decoded event data - The simulator that generated the event + An containing the objects data - + - Permission request flags, asked when a script wants to control an Avatar + Deserialize the message + An containing the data - - Placeholder for empty values, shouldn't ever see this - - - Script wants ability to take money from you - - - Script wants to take camera controls for you - - - Script wants to remap avatars controls - - - Script wants to trigger avatar animations - This function is not implemented on the grid - - - Script wants to attach or detach the prim or primset to your avatar - - - Script wants permission to release ownership - This function is not implemented on the grid - The concept of "public" objects does not exist anymore. - - - Script wants ability to link/delink with other prims - - - Script wants permission to change joints - This function is not implemented on the grid - - - Script wants permissions to change permissions - This function is not implemented on the grid - - - Script wants to track avatars camera position and rotation - - - Script wants to control your camera + + + A reusable class containing a message sent from the viewer to the simulator to request a temporary uploader capability + which is used to update an asset in an agents inventory + - - Script wants the ability to teleport you + + + The Notecard AssetID to replace + - + - Special commands used in Instant Messages + Serialize the object + An containing the objects data - - Indicates a regular IM from another agent + + + Deserialize the message + + An containing the data - - Simple notification box with an OK button + + + A message containing the request/response used for updating a notecard + contained with an agents inventory + - - You've been invited to join a group. + + Object containing request or response - - Inventory offer + + + Serialize the object + + An containing the objects data - - Accepted inventory offer + + + Deserialize the message + + An containing the data - - Declined inventory offer + + + Serialize the object + + An containing the objects data - - Group vote + + + Deserialize the message + + An containing the data - - An object is offering its inventory + + + A message sent from the simulator to the viewer which indicates + an error occurred while attempting to update a script in an agents or tasks + inventory + - - Accept an inventory offer from an object + + true of the script was successfully compiled by the simulator - - Decline an inventory offer from an object + + A string containing the error which occured while trying + to update the script - - Unknown + + A new AssetID assigned to the script - - Start a session, or add users to a session + + + A message sent from the viewer to the simulator + requesting the update of an existing script contained + within a tasks inventory + - - Start a session, but don't prune offline users + + if true, set the script mode to running - - Start a session with your group + + The scripts InventoryItem ItemID to update - - Start a session without a calling card (finder or objects) + + A lowercase string containing either "mono" or "lsl2" which + specifies the script is compiled and ran on the mono runtime, or the older + lsl runtime - - Send a message to a session + + The tasks which contains the script to update - - Leave a session + + + Serialize the object + + An containing the objects data - - Indicates that the IM is from an object + + + Deserialize the message + + An containing the data - - Sent an IM to a busy user, this is the auto response + + + A message containing either the request or response used in updating a script inside + a tasks inventory + - - Shows the message in the console and chat history + + Object containing request or response - - Send a teleport lure + + + Serialize the object + + An containing the objects data - - Response sent to the agent which inititiated a teleport invitation + + + Deserialize the message + + An containing the data - - Response sent to the agent which inititiated a teleport invitation + + + Response from the simulator to notify the viewer the upload is completed, and + the UUID of the script asset and its compiled status + - - Only useful if you have Linden permissions + + The uploaded texture asset ID - - Request a teleport lure + + true of the script was compiled successfully - - IM to tell the user to go to an URL + + + A message sent from a viewer to the simulator requesting a temporary uploader capability + used to update a script contained in an agents inventory + - - IM for help + + The existing asset if of the script in the agents inventory to replace - - IM sent automatically on call for help, sends a lure - to each Helper reached + + The language of the script + Defaults to lsl version 2, "mono" might be another possible option - - Like an IM but won't go to email + + + Serialize the object + + An containing the objects data - - IM from a group officer to all group members + + + Deserialize the message + + An containing the data - - Unknown + + + A message containing either the request or response used in updating a script inside + an agents inventory + - - Unknown + + Object containing request or response - - Accept a group invitation + + + Serialize the object + + An containing the objects data - - Decline a group invitation + + + Deserialize the message + + An containing the data - - Unknown + + + Serialize the object + + An containing the objects data - - An avatar is offering you friendship + + + Deserialize the message + + An containing the data - - An avatar has accepted your friendship offer + + Base class for Map Layers via Capabilities - - An avatar has declined your friendship offer + + - - Indicates that a user has started typing + + + Serialize the object + + An containing the objects data - - Indicates that a user has stopped typing + + + Deserialize the message + + An containing the data - + - Flag in Instant Messages, whether the IM should be delivered to - offline avatars as well + Sent by an agent to the capabilities server to request map layers - - Only deliver to online avatars + + + A message sent from the simulator to the viewer which contains an array of map images and their grid coordinates + - - If the avatar is offline the message will be held until - they login next, and possibly forwarded to their e-mail account + + An array containing LayerData items - + - Conversion type to denote Chat Packet types in an easier-to-understand format + Serialize the object + An containing the objects data - - Whisper (5m radius) + + + Deserialize the message + + An containing the data - - Normal chat (10/20m radius), what the official viewer typically sends + + + An object containing map location details + - - Shouting! (100m radius) + + The Asset ID of the regions tile overlay - - Event message when an Avatar has begun to type + + The grid location of the southern border of the map tile - - Event message when an Avatar has stopped typing + + The grid location of the western border of the map tile - - Send the message to the debug channel + + The grid location of the eastern border of the map tile - - Event message when an object uses llOwnerSay + + The grid location of the northern border of the map tile - - Special value to support llRegionSay, never sent to the client + + Object containing request or response - + - Identifies the source of a chat message + Serialize the object + An containing the objects data - - Chat from the grid or simulator + + + Deserialize the message + + An containing the data - - Chat from another avatar + + + New as of 1.23 RC1, no details yet. + - - Chat from an object + + + Serialize the object + + An containing the objects data - + - + Deserialize the message + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + A string containing the method used - + - Effect type used in ViewerEffect packets - + A request sent from an agent to the Simulator to begin a new conference. + Contains a list of Agents which will be included in the conference + - - + + An array containing the of the agents invited to this conference - - + + The conferences Session ID - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + A moderation request sent from a conference moderator + Contains an agent and an optional action to take + - + + The Session ID + + - + + A list containing Key/Value pairs, known valid values: + key: text value: true/false - allow/disallow specified agents ability to use text in session + key: voice value: true/false - allow/disallow specified agents ability to use voice in session + + "text" or "voice" + + - - Project a beam from a source to a destination, such as - the one used when editing an object + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + A message sent from the agent to the simulator which tells the + simulator we've accepted a conference invitation + - - + + The conference SessionID - - Create a swirl of particles around an object + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - Cause an avatar to look at an object + + + Deserialize the message + + An containing the data - - Cause an avatar to point at an object + + + Serialize the object + + An containing the objects data - + - The action an avatar is doing when looking at something, used in - ViewerEffect packets for the LookAt effect + Deserialize the message + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + Key of sender - - + + Name of sender - - + + Key of destination avatar - - + + ID of originating estate - - Deprecated + + Key of originating region - - + + Coordinates in originating region - - + + Instant message type - - + + Group IM session toggle - - + + Key of IM session, for Group Messages, the groups UUID - - - The action an avatar is doing when pointing at something, used in - ViewerEffect packets for the PointAt effect - + + Timestamp of the instant message - - + + Instant message text - - + + Whether this message is held for offline avatars - - + + Context specific packed data - - + + Is this invitation for voice group/conference chat - + - Money transaction types + Serialize the object + An containing the objects data - - - - - - - - + + + Deserialize the message + + An containing the data - - + + + Sent from the simulator to the viewer. + + When an agent initially joins a session the AgentUpdatesBlock object will contain a list of session members including + a boolean indicating they can use voice chat in this session, a boolean indicating they are allowed to moderate + this session, and lastly a string which indicates another agent is entering the session with the Transition set to "ENTER" + + During the session lifetime updates on individuals are sent. During the update the booleans sent during the initial join are + excluded with the exception of the Transition field. This indicates a new user entering or exiting the session with + the string "ENTER" or "LEAVE" respectively. + - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + An EventQueue message sent when the agent is forcibly removed from a chatterbox session + - - + + + A string containing the reason the agent was removed + - - + + + The ChatterBoxSession's SessionID + - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + + - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + Event Queue message describing physics engine attributes of a list of objects + Sim sends these when object is selected + - - + + Array with the list of physics properties - - + + + Serializes the message + + Serialized OSD - - + + + Deseializes the message + + Incoming data to deserialize - - + + + A message sent from the viewer to the simulator which + specifies that the user has changed current URL + of the specific media on a prim face + - - + + + New URL + - - + + + Prim UUID where navigation occured + - - + + + Face index + - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + Base class used for the ObjectMedia message - - + + + Message used to retrive prim media data + - - + + + Prim UUID + - - + + + Requested operation, either GET or UPDATE + - - + + + Serialize object + + Serialized object as OSDMap - - + + + Deserialize the message + + An containing the data - - + + + Message used to update prim media data + - - + + + Prim UUID + - - + + + Array of media entries indexed by face number + - - + + + Media version string + - - + + + Serialize object + + Serialized object as OSDMap - - + + + Deserialize the message + + An containing the data - - + + + Message used to update prim media data + - - + + + Prim UUID + - + - + Array of media entries indexed by face number - - + + + Requested operation, either GET or UPDATE + - - + + + Serialize object + + Serialized object as OSDMap - - + + + Deserialize the message + + An containing the data - - + + + Message for setting or getting per face MediaEntry + - - + + The request or response details block - - + + + Serialize the object + + An containing the objects data - + - + Deserialize the message + An containing the data - - + + Details about object resource usage - - + + Object UUID - - + + Object name - - + + Indicates if object is group owned - - + + Locatio of the object - - + + Object owner - + + Resource usage, keys are resource names, values are resource usage for that specific resource + + - Flags sent when a script takes or releases a control + Deserializes object from OSD - NOTE: (need to verify) These might be a subset of the ControlFlags enum in Movement, - - - No Flags set - - - Forward (W or up Arrow) - - - Back (S or down arrow) + An containing the data - - Move left (shift+A or left arrow) + + + Makes an instance based on deserialized data + + serialized data + Instance containg deserialized data - - Move right (shift+D or right arrow) + + Details about parcel resource usage - - Up (E or PgUp) + + Parcel UUID - - Down (C or PgDown) + + Parcel local ID - - Rotate left (A or left arrow) + + Parcel name - - Rotate right (D or right arrow) + + Indicates if parcel is group owned - - Left Mouse Button + + Parcel owner - - Left Mouse button in MouseLook + + Array of containing per object resource usage - + - Currently only used to hide your group title + Deserializes object from OSD + An containing the data - - No flags set - - - Hide your group title - - + - Action state of the avatar, which can currently be typing and - editing + Makes an instance based on deserialized data + serialized data + Instance containg deserialized data - - + + Resource usage base class, both agent and parcel resource + usage contains summary information - - + + Summary of available resources, keys are resource names, + values are resource usage for that specific resource - - + + Summary resource usage, keys are resource names, + values are resource usage for that specific resource - + - Current teleport status + Serializes object + serialized data - - Unknown status - - - Teleport initialized - - - Teleport in progress - - - Teleport failed + + + Deserializes object from OSD + + An containing the data - - Teleport completed + + Agent resource usage - - Teleport cancelled + + Per attachment point object resource usage - + - + Deserializes object from OSD + An containing the data - - No flags set, or teleport failed - - - Set when newbie leaves help island for first time + + + Makes an instance based on deserialized data + + serialized data + Instance containg deserialized data - - + + + Detects which class handles deserialization of this message + + An containing the data + Object capable of decoding this message - - Via Lure + + Request message for parcel resource usage - - Via Landmark + + UUID of the parel to request resource usage info - - Via Location + + + Serializes object + + serialized data - - Via Home + + + Deserializes object from OSD + + An containing the data - - Via Telehub + + Response message for parcel resource usage - - Via Login + + URL where parcel resource usage details can be retrieved - - Linden Summoned + + URL where parcel resource usage summary can be retrieved - - Linden Forced me + + + Serializes object + + serialized data - - + + + Deserializes object from OSD + + An containing the data - - Agent Teleported Home via Script + + + Detects which class handles deserialization of this message + + An containing the data + Object capable of decoding this message - - + + Parcel resource usage - - + + Array of containing per percal resource usage - - + + + Deserializes object from OSD + + An containing the data - - forced to new location for example when avatar is banned or ejected + + + Reply to request for bunch if display names + - - Teleport Finished via a Lure + + Current display name - - Finished, Sim Changed + + Following UUIDs failed to return a valid display name - - Finished, Same Sim + + + Serializes the message + + OSD containting the messaage - + - + Message sent when requesting change of the display name - - + + Current display name - - + + Desired new display name - - + + + Serializes the message + + OSD containting the messaage - + - + Message recieved in response to request to change display name - - + + New display name - - + + String message indicating the result of the operation - - + + Numerical code of the result, 200 indicates success - - + + + Serializes the message + + OSD containting the messaage - + - Type of mute entry + Message recieved when someone nearby changes their display name - - Object muted by name + + Previous display name, empty string if default - - Muted residet + + New display name - - Object muted by UUID + + + Serializes the message + + OSD containting the messaage - - Muted group + + + Return a decoded capabilities message as a strongly typed object + + A string containing the name of the capabilities message key + An to decode + A strongly typed object containing the decoded information from the capabilities message, or null + if no existing Message object exists for the specified event - - Muted external entry + + + Permissions for control of object media + - + - Flags of mute entry + Style of cotrols that shold be displayed to the user - - No exceptions + + + Class representing media data for a single face + - - Don't mute text chat + + Is display of the alternative image enabled - - Don't mute voice chat + + Should media auto loop - - Don't mute particles + + Shoule media be auto played - - Don't mute sounds + + Auto scale media to prim face - - Don't mute + + Should viewer automatically zoom in on the face when clicked - - - Instant Message - + + Should viewer interpret first click as interaction with the media + or when false should the first click be treated as zoom in commadn - - Key of sender + + Style of controls viewer should display when + viewer media on this face - - Name of sender + + Starting URL for the media - - Key of destination avatar + + Currently navigated URL - - ID of originating estate + + Media height in pixes - - Key of originating region + + Media width in pixels - - Coordinates in originating region + + Who can controls the media - - Instant message type + + Who can interact with the media - - Group IM session toggle + + Is URL whitelist enabled - - Key of IM session, for Group Messages, the groups UUID + + Array of URLs that are whitelisted - - Timestamp of the instant message + + + Serialize to OSD + + OSDMap with the serialized data - - Instant message text + + + Deserialize from OSD data + + Serialized OSD data + Deserialized object - - Whether this message is held for offline avatars + + + The type of bump-mapping applied to a face + - - Context specific packed data + + - - Print the struct data as a string - A string containing the field name, and field value + + - - Represents muted object or resident + + - - Type of the mute entry + + - - UUID of the mute etnry + + - - Mute entry name + + - - Mute flags + + - - Transaction detail sent with MoneyBalanceReply message + + - - Type of the transaction + + - - UUID of the transaction source + + - - Is the transaction source a group + + - - UUID of the transaction destination + + - - Is transaction destination a group + + - - Transaction amount + + - - Transaction description + + - - - - + + - - - Construct a new instance of the ChatEventArgs object - - Sim from which the message originates - The message sent - The audible level of the message - The type of message sent: whisper, shout, etc - The source type of the message sender - The name of the agent or object sending the message - The ID of the agent or object sending the message - The ID of the object owner, or the agent ID sending the message - The position of the agent or object sending the message + + - - Get the simulator sending the message + + - - Get the message sent + + + The level of shininess applied to a face + - - Get the audible level of the message + + - - Get the type of message sent: whisper, shout, etc + + - - Get the source type of the message sender + + - - Get the name of the agent or object sending the message + + - - Get the ID of the agent or object sending the message + + + The texture mapping style used for a face + - - Get the ID of the object owner, or the agent ID sending the message + + - - Get the position of the agent or object sending the message + + - - Contains the data sent when a primitive opens a dialog with this agent + + - + + + + - Construct a new instance of the ScriptDialogEventArgs + Flags in the TextureEntry block that describe which properties are + set - The dialog message - The name of the object that sent the dialog request - The ID of the image to be displayed - The ID of the primitive sending the dialog - The first name of the senders owner - The last name of the senders owner - The communication channel the dialog was sent on - The string labels containing the options presented in this dialog - UUID of the scritped object owner - - Get the dialog message + + - - Get the name of the object that sent the dialog request + + - - Get the ID of the image to be displayed + + - - Get the ID of the primitive sending the dialog + + - - Get the first name of the senders owner + + - - Get the last name of the senders owner + + - - Get the communication channel the dialog was sent on, responses - should also send responses on this same channel + + - - Get the string labels containing the options presented in this dialog + + - - UUID of the scritped object owner + + - - Contains the data sent when a primitive requests debit or other permissions - requesting a YES or NO answer + + - - - Construct a new instance of the ScriptQuestionEventArgs - - The simulator containing the object sending the request - The ID of the script making the request - The ID of the primitive containing the script making the request - The name of the primitive making the request - The name of the owner of the object making the request - The permissions being requested + + - - Get the simulator containing the object sending the request + + - - Get the ID of the script making the request + + - - Get the ID of the primitive containing the script making the request + + + Level of Detail mesh + - - Get the name of the primitive making the request + + + Contains all mesh faces that belong to a prim + - - Get the name of the owner of the object making the request + + List of primitive faces - - Get the permissions being requested + + + Decodes mesh asset into FacetedMesh + + Mesh primitive + Asset retrieved from the asset server + Level of detail + Resulting decoded FacetedMesh + True if mesh asset decoding was successful - - Contains the data sent when a primitive sends a request - to an agent to open the specified URL + + + This is used to login a specific user account(s). It may only be called after + Connector initialization has completed successfully + + Handle returned from successful Connector ‘create’ request + User's account name + User's account password + Values may be “AutoAnswer” or “VerifyAnswer” + "" + This is an integer that specifies how often + the daemon will send participant property events while in a channel. If this is not set + the default will be “on state change”, which means that the events will be sent when + the participant starts talking, stops talking, is muted, is unmuted. + The valid values are: + 0 – Never + 5 – 10 times per second + 10 – 5 times per second + 50 – 1 time per second + 100 – on participant state change (this is the default) + false + - + - Construct a new instance of the LoadUrlEventArgs + This is used to logout a user session. It should only be called with a valid AccountHandle. - The name of the object sending the request - The ID of the object sending the request - The ID of the owner of the object sending the request - True if the object is owned by a group - The message sent with the request - The URL the object sent + Handle returned from successful Connector ‘login’ request + - - Get the name of the object sending the request + + + This is used to get a list of audio devices that can be used for capture (input) of voice. + + - - Get the ID of the object sending the request + + + This is used to get a list of audio devices that can be used for render (playback) of voice. + - - Get the ID of the owner of the object sending the request + + + This command is used to select the render device. + + The name of the device as returned by the Aux.GetRenderDevices command. - - True if the object is owned by a group + + + This command is used to select the capture device. + + The name of the device as returned by the Aux.GetCaptureDevices command. - - Get the message sent with the request + + + This command is used to start the audio capture process which will cause + AuxAudioProperty Events to be raised. These events can be used to display a + microphone VU meter for the currently selected capture device. This command + should not be issued if the user is on a call. + + (unused but required) + - - Get the URL the object sent + + + This command is used to stop the audio capture process. + + - - The date received from an ImprovedInstantMessage + + + This command is used to set the mic volume while in the audio tuning process. + Once an acceptable mic level is attained, the application must issue a + connector set mic volume command to have that level be used while on voice + calls. + + the microphone volume (-100 to 100 inclusive) + - + + + This command is used to set the speaker volume while in the audio tuning + process. Once an acceptable speaker level is attained, the application must + issue a connector set speaker volume command to have that level be used while + on voice calls. + + the speaker volume (-100 to 100 inclusive) + + + - Construct a new instance of the InstantMessageEventArgs object + This is used to initialize and stop the Connector as a whole. The Connector + Create call must be completed successfully before any other requests are made + (typically during application initialization). The shutdown should be called + when the application is shutting down to gracefully release resources - the InstantMessage object - the simulator where the InstantMessage origniated - - - Get the InstantMessage object - - - Get the simulator where the InstantMessage origniated - - - Contains the currency balance + A string value indicting the Application name + URL for the management server + LoggingSettings + + - + - Construct a new BalanceEventArgs object + Shutdown Connector -- Should be called when the application is shutting down + to gracefully release resources - The currenct balance + Handle returned from successful Connector ‘create’ request - + - Get the currenct balance + Mute or unmute the microphone + Handle returned from successful Connector ‘create’ request + true (mute) or false (unmute) - - Contains the transaction summary when an item is purchased, - money is given, or land is purchased - - + - Construct a new instance of the MoneyBalanceReplyEventArgs object + Mute or unmute the speaker - The ID of the transaction - True of the transaction was successful - The current currency balance - The meters credited - The meters comitted - A brief description of the transaction - Transaction info + Handle returned from successful Connector ‘create’ request + true (mute) or false (unmute) - - Get the ID of the transaction + + + Set microphone volume + + Handle returned from successful Connector ‘create’ request + The level of the audio, a number between -100 and 100 where + 0 represents ‘normal’ speaking volume - - True of the transaction was successful + + + Set local speaker volume + + Handle returned from successful Connector ‘create’ request + The level of the audio, a number between -100 and 100 where + 0 represents ‘normal’ speaking volume - - Get the remaining currency balance + + + Start up the Voice service. + - - Get the meters credited + + + Handle miscellaneous request status + + + + ///If something goes wrong, we log it. - - Get the meters comitted + + + Cleanup oject resources + - - Get the description of the transaction + + + Request voice cap when changing regions + - - Detailed transaction information + + + Handle a change in session state + - - Data sent from the simulator containing information about your agent and active group information + + + Close a voice session + + - + - Construct a new instance of the AgentDataReplyEventArgs object + Locate a Session context from its handle - The agents first name - The agents last name - The agents active group ID - The group title of the agents active group - The combined group powers the agent has in the active group - The name of the group the agent has currently active + Creates the session context if it does not exist. - - Get the agents first name + + + Handle completion of main voice cap request. + + + + - - Get the agents last name + + + Daemon has started so connect to it. + - - Get the active group ID of your agent + + + The daemon TCP connection is open. + - - Get the active groups title of your agent + + + Handle creation of the Connector. + - - Get the combined group powers of your agent + + + Handle response to audio output device query + - - Get the active group name of your agent + + + Handle response to audio input device query + - - Data sent by the simulator to indicate the active/changed animations - applied to your agent + + + Set voice channel for new parcel + + - + - Construct a new instance of the AnimationsChangedEventArgs class + Request info from a parcel capability Uri. - The dictionary that contains the changed animations - - - Get the dictionary that contains the changed animations + - + - Data sent from a simulator indicating a collision with your agent + Receive parcel voice cap + + + - + - Construct a new instance of the MeanCollisionEventArgs class + Tell Vivox where we are standing - The type of collision that occurred - The ID of the agent or object that perpetrated the agression - The ID of the Victim - The strength of the collision - The Time the collision occurred + This has to be called when we move or turn. - - Get the Type of collision + + + Start and stop updating out position. + + - - Get the ID of the agent or object that collided with your agent + + + Starts a thread that keeps the daemon running + + + - - Get the ID of the agent that was attacked + + + Stops the daemon and the thread keeping it running + - - A value indicating the strength of the collision + + + + + + + - - Get the time the collision occurred + + + Create a Session + Sessions typically represent a connection to a media session with one or more + participants. This is used to generate an ‘outbound’ call to another user or + channel. The specifics depend on the media types involved. A session handle is + required to control the local user functions within the session (or remote + users if the current account has rights to do so). Currently creating a + session automatically connects to the audio media, there is no need to call + Session.Connect at this time, this is reserved for future use. + + Handle returned from successful Connector ‘create’ request + This is the URI of the terminating point of the session (ie who/what is being called) + This is the display name of the entity being called (user or channel) + Only needs to be supplied when the target URI is password protected + This indicates the format of the password as passed in. This can either be + “ClearText” or “SHA1UserName”. If this element does not exist, it is assumed to be “ClearText”. If it is + “SHA1UserName”, the password as passed in is the SHA1 hash of the password and username concatenated together, + then base64 encoded, with the final “=” character stripped off. + + + - - Data sent to your agent when it crosses region boundaries + + + Used to accept a call + + SessionHandle such as received from SessionNewEvent + "default" + - + - Construct a new instance of the RegionCrossedEventArgs class + This command is used to start the audio render process, which will then play + the passed in file through the selected audio render device. This command + should not be issued if the user is on a call. - The simulator your agent just left - The simulator your agent is now in - - - Get the simulator your agent just left - - - Get the simulator your agent is now in - - - Data sent from the simulator when your agent joins a group chat session + The fully qualified path to the sound file. + True if the file is to be played continuously and false if it is should be played once. + - + - Construct a new instance of the GroupChatJoinedEventArgs class + This command is used to stop the audio render process. - The ID of the session - The name of the session - A temporary session id used for establishing new sessions - True of your agent successfully joined the session - - - Get the ID of the group chat session - - - Get the name of the session - - - Get the temporary session ID used for establishing new sessions - - - True if your agent successfully joined the session - - - Data sent by the simulator containing urgent messages + The fully qualified path to the sound file issued in the start render command. + - + - Construct a new instance of the AlertMessageEventArgs class + This is used to ‘end’ an established session (i.e. hang-up or disconnect). - The alert message - - - Get the alert message - - - Data sent by a script requesting to take or release specified controls to your agent + Handle returned from successful Session ‘create’ request or a SessionNewEvent + - + - Construct a new instance of the ScriptControlEventArgs class + Set the combined speaking and listening position in 3D space. - The controls the script is attempting to take or release to the agent - True if the script is passing controls back to the agent - True if the script is requesting controls be released to the script - - - Get the controls the script is attempting to take or release to the agent - - - True if the script is passing controls back to the agent - - - True if the script is requesting controls be released to the script + Handle returned from successful Session ‘create’ request or a SessionNewEvent + Speaking position + Listening position + - + - Data sent from the simulator to an agent to indicate its view limits + Set User Volume for a particular user. Does not affect how other users hear that user. + Handle returned from successful Session ‘create’ request or a SessionNewEvent + + The level of the audio, a number between -100 and 100 where 0 represents ‘normal’ speaking volume + - + - Construct a new instance of the CameraConstraintEventArgs class + List of audio input devices - The collision plane - - - Get the collision plane - + - Data containing script sensor requests which allow an agent to know the specific details - of a primitive sending script sensor requests + List of audio output devices - + - Construct a new instance of the ScriptSensorReplyEventArgs + Set audio test mode - The ID of the primitive sending the sensor - The ID of the group associated with the primitive - The name of the primitive sending the sensor - The ID of the primitive sending the sensor - The ID of the owner of the primitive sending the sensor - The position of the primitive sending the sensor - The range the primitive specified to scan - The rotation of the primitive sending the sensor - The type of sensor the primitive sent - The velocity of the primitive sending the sensor - - - Get the ID of the primitive sending the sensor - - Get the ID of the group associated with the primitive + + + Event for most mundane request reposnses. + - - Get the name of the primitive sending the sensor + + Response to Connector.Create request - - Get the ID of the primitive sending the sensor + + Response to Aux.GetCaptureDevices request - - Get the ID of the owner of the primitive sending the sensor + + Response to Aux.GetRenderDevices request - - Get the position of the primitive sending the sensor + + Audio Properties Events are sent after audio capture is started. + These events are used to display a microphone VU meter - - Get the range the primitive specified to scan + + Response to Account.Login request - - Get the rotation of the primitive sending the sensor + + This event message is sent whenever the login state of the + particular Account has transitioned from one value to another - - Get the type of sensor the primitive sent + + Enable logging - - Get the velocity of the primitive sending the sensor + + The folder where any logs will be created - - Contains the response data returned from the simulator in response to a + + This will be prepended to beginning of each log file - - Construct a new instance of the AvatarSitResponseEventArgs object + + The suffix or extension to be appended to each log file - - Get the ID of the primitive the agent will be sitting on + + + 0: NONE - No logging + 1: ERROR - Log errors only + 2: WARNING - Log errors and warnings + 3: INFO - Log errors, warnings and info + 4: DEBUG - Log errors, warnings, info and debug + - - True if the simulator Autopilot functions were involved + + + Constructor for default logging settings + - - Get the camera offset of the agent when seated + + Audio Properties Events are sent after audio capture is started. These events are used to display a microphone VU meter - - Get the camera eye offset of the agent when seated + + Positional vector of the users position - - True of the agent will be in mouselook mode when seated + + Velocity vector of the position - - Get the position of the agent when seated + + At Orientation (X axis) of the position - - Get the rotation of the agent when seated + + Up Orientation (Y axis) of the position - - Data sent when an agent joins a chat session your agent is currently participating in + + Left Orientation (Z axis) of the position - + - Construct a new instance of the ChatSessionMemberAddedEventArgs object + Extract the avatar UUID encoded in a SIP URI - The ID of the chat session - The ID of the agent joining - - - Get the ID of the chat session - - - Get the ID of the agent that joined - - - Data sent when an agent exits a chat session your agent is currently participating in + + - + - Construct a new instance of the ChatSessionMemberLeftEventArgs object + Represents a single Voice Session to the Vivox service. - The ID of the chat session - The ID of the Agent that left - - - Get the ID of the chat session - - - Get the ID of the agent that left - - - Event arguments with the result of setting display name operation - - - Default constructor - - - Status code, 200 indicates settign display name was successful - - Textual description of the status + + + Close this session. + - - Details of the newly set display name + + + Look up an existing Participants in this session + + + diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index 7bc870b..1f83c3a 100755 Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ diff --git a/bin/OpenMetaverseTypes.XML b/bin/OpenMetaverseTypes.XML index 5280485..a0c9135 100644 --- a/bin/OpenMetaverseTypes.XML +++ b/bin/OpenMetaverseTypes.XML @@ -4,1903 +4,2004 @@ OpenMetaverseTypes - - For thread safety - - - For thread safety - - + - Purges expired objects from the cache. Called automatically by the purge timer. + Same as Queue except Dequeue function blocks until there is an object to return. + Note: This class does not need to be synchronized - + - Determines the appropriate events to set, leaves the locks, and sets the events. + Create new BlockingQueue. + The System.Collections.ICollection to copy elements from - + - A routine for lazily creating a event outside the lock (so if errors - happen they are outside the lock and that we don't do much work - while holding a spin lock). If all goes well, reenter the lock and - set 'waitEvent' + Create new BlockingQueue. + The initial number of elements that the queue can contain - + - Waits on 'waitEvent' with a timeout of 'millisceondsTimeout. - Before the wait 'numWaiters' is incremented and is restored before leaving this routine. + Create new BlockingQueue. - - X value - - - Y value - - - Z value - - - W value - - + - Build a quaternion from normalized float values + BlockingQueue Destructor (Close queue, resume any waiting thread). - X value from -1.0 to 1.0 - Y value from -1.0 to 1.0 - Z value from -1.0 to 1.0 - + - Constructor, builds a quaternion object from a byte array + Remove all objects from the Queue. - Byte array containing four four-byte floats - Offset in the byte array to start reading at - Whether the source data is normalized or - not. If this is true 12 bytes will be read, otherwise 16 bytes will - be read. - + - Normalizes the quaternion + Remove all objects from the Queue, resume all dequeue threads. - + - Builds a quaternion object from a byte array + Removes and returns the object at the beginning of the Queue. - The source byte array - Offset in the byte array to start reading at - Whether the source data is normalized or - not. If this is true 12 bytes will be read, otherwise 16 bytes will - be read. + Object in queue. - + - Normalize this quaternion and serialize it to a byte array + Removes and returns the object at the beginning of the Queue. - A 12 byte array containing normalized X, Y, and Z floating - point values in order using little endian byte ordering + time to wait before returning + Object in queue. - + - Writes the raw bytes for this quaternion to a byte array + Removes and returns the object at the beginning of the Queue. - Destination byte array - Position in the destination array to start - writing. Must be at least 12 bytes before the end of the array + time to wait before returning (in milliseconds) + Object in queue. - + - Convert this quaternion to euler angles + Adds an object to the end of the Queue - X euler angle - Y euler angle - Z euler angle + Object to put in queue - + - Convert this quaternion to an angle around an axis + Open Queue. - Unit vector describing the axis - Angle around the axis, in radians - + - Returns the conjugate (spatial inverse) of a quaternion + Gets flag indicating if queue has been closed. - + - Build a quaternion from an axis and an angle of rotation around - that axis + Copy constructor + Circular queue to copy - + - Build a quaternion from an axis and an angle of rotation around - that axis + An 8-bit color structure including an alpha channel - Axis of rotation - Angle of rotation - - - Creates a quaternion from a vector containing roll, pitch, and yaw - in radians - - Vector representation of the euler angles in - radians - Quaternion representation of the euler angles + + Red - - - Creates a quaternion from roll, pitch, and yaw euler angles in - radians - - X angle in radians - Y angle in radians - Z angle in radians - Quaternion representation of the euler angles + + Green - - - Conjugates and renormalizes a vector - + + Blue - - - Spherical linear interpolation between two quaternions - + + Alpha - + - Get a string representation of the quaternion elements with up to three - decimal digits and separated by spaces only + - Raw string representation of the quaternion - - - A quaternion with a value of 0,0,0,1 + + + + - + - A three-dimensional vector with doubleing-point values + Builds a color from a byte array + Byte array containing a 16 byte color + Beginning position in the byte array + True if the byte array stores inverted values, + otherwise false. For example the color black (fully opaque) inverted + would be 0xFF 0xFF 0xFF 0x00 - - X value - - - Y value - - - Z value - - + - Constructor, builds a vector from a byte array + Returns the raw bytes for this vector - Byte array containing three eight-byte doubles + Byte array containing a 16 byte color Beginning position in the byte array + True if the byte array stores inverted values, + otherwise false. For example the color black (fully opaque) inverted + would be 0xFF 0xFF 0xFF 0x00 + True if the alpha value is inverted in + addition to whatever the inverted parameter is. Setting inverted true + and alphaInverted true will flip the alpha value back to non-inverted, + but keep the other color bytes inverted + A 16 byte array containing R, G, B, and A - + - Test if this vector is equal to another vector, within a given - tolerance range + Copy constructor - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false + Color to copy - + IComparable.CompareTo implementation + Sorting ends up like this: |--Grayscale--||--Color--|. + Alpha is only used when the colors are otherwise equivalent - + - Test if this vector is composed of all finite numbers + Builds a color from a byte array + Byte array containing a 16 byte color + Beginning position in the byte array + True if the byte array stores inverted values, + otherwise false. For example the color black (fully opaque) inverted + would be 0xFF 0xFF 0xFF 0x00 + True if the alpha value is inverted in + addition to whatever the inverted parameter is. Setting inverted true + and alphaInverted true will flip the alpha value back to non-inverted, + but keep the other color bytes inverted - + - Builds a vector from a byte array + Writes the raw bytes for this color to a byte array - Byte array containing a 24 byte vector - Beginning position in the byte array + Destination byte array + Position in the destination array to start + writing. Must be at least 16 bytes before the end of the array - + - Returns the raw bytes for this vector + Serializes this color into four bytes in a byte array - A 24 byte array containing X, Y, and Z + Destination byte array + Position in the destination array to start + writing. Must be at least 4 bytes before the end of the array + True to invert the output (1.0 becomes 0 + instead of 255) - + - Writes the raw bytes for this vector to a byte array + Writes the raw bytes for this color to a byte array Destination byte array Position in the destination array to start - writing. Must be at least 24 bytes before the end of the array + writing. Must be at least 16 bytes before the end of the array - + - Parse a vector from a string + Ensures that values are in range 0-1 - A string representation of a 3D vector, enclosed - in arrow brackets and separated by commas - + - Interpolates between two vectors using a cubic equation + Create an RGB color from a hue, saturation, value combination + Hue + Saturation + Value + An fully opaque RGB color (alpha is 1.0) - + - Get a formatted string representation of the vector + Performs linear interpolation between two colors - A string representation of the vector + Color to start at + Color to end at + Amount to interpolate + The interpolated color - - - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only - - Raw string representation of the vector + + A Color4 with zero RGB values and fully opaque (alpha 1.0) - + + A Color4 with full RGB values (1.0) and fully opaque (alpha 1.0) + + - Cross product between two vectors + Attribute class that allows extra attributes to be attached to ENUMs - + + Text used when presenting ENUM to user + + + Default initializer + + + Text used when presenting ENUM to user + + - Implicit casting for Vector3 > Vector3d + The different types of grid assets - - - - A vector with a value of 0,0,0 + + Unknown asset type - - A vector with a value of 1,1,1 + + Texture asset, stores in JPEG2000 J2C stream format - - A unit vector facing forward (X axis), value of 1,0,0 + + Sound asset - - A unit vector facing left (Y axis), value of 0,1,0 + + Calling card for another avatar - - A unit vector facing up (Z axis), value of 0,0,1 + + Link to a location in world - - - A thread-safe lockless queue that supports multiple readers and - multiple writers - + + Collection of textures and parameters that can be + worn by an avatar - - Queue head + + Primitive that can contain textures, sounds, + scripts and more - - Queue tail + + Notecard asset - - Queue item count + + Holds a collection of inventory items - - - Constructor - + + Root inventory folder - - - Enqueue an item - - Item to enqeue + + Linden scripting language script - - - Try to dequeue an item - - Dequeued item if the dequeue was successful - True if an item was successfully deqeued, otherwise false + + LSO bytecode for a script - - Gets the current number of items in the queue. Since this - is a lockless collection this value should be treated as a close - estimate + + Uncompressed TGA texture - - - Provides a node container for data in a singly linked list - + + Collection of textures and shape parameters that can + be worn - - Pointer to the next node in list + + Trash folder - - The data contained by the node + + Snapshot folder - - - Constructor - + + Lost and found folder - - - Constructor - + + Uncompressed sound - - - Convert this matrix to euler rotations - - X euler angle - Y euler angle - Z euler angle + + Uncompressed TGA non-square image, not to be used as a + texture - - - Convert this matrix to a quaternion rotation - - A quaternion representation of this rotation matrix + + Compressed JPEG non-square image, not to be used as a + texture - - - Construct a matrix from euler rotation values in radians - - X euler angle in radians - Y euler angle in radians - Z euler angle in radians + + Animation - - - Get a formatted string representation of the vector - - A string representation of the vector + + Sequence of animations, sounds, chat, and pauses - - A 4x4 matrix containing all zeroes + + Simstate file - - A 4x4 identity matrix + + Contains landmarks for favorites - - Used for converting degrees to radians + + Asset is a link to another inventory item - - Used for converting radians to degrees + + Asset is a link to another inventory folder - - - Convert the first two bytes starting in the byte array in - little endian ordering to a signed short integer - - An array two bytes or longer - A signed short integer, will be zero if a short can't be - read at the given position + + Beginning of the range reserved for ensembles - - - Convert the first two bytes starting at the given position in - little endian ordering to a signed short integer - - An array two bytes or longer - Position in the array to start reading - A signed short integer, will be zero if a short can't be - read at the given position + + End of the range reserved for ensembles - - - Convert the first four bytes starting at the given position in - little endian ordering to a signed integer - - An array four bytes or longer - Position to start reading the int from - A signed integer, will be zero if an int can't be read - at the given position + + Folder containing inventory links to wearables and attachments + that are part of the current outfit - + + Folder containing inventory items or links to + inventory items of wearables and attachments + together make a full outfit + + + Root folder for the folders of type OutfitFolder + + + Linden mesh format + + + Marketplace direct delivery inbox ("Received Items") + + + Marketplace direct delivery outbox + + + + + - Convert the first four bytes of the given array in little endian - ordering to a signed integer + Inventory Item Types, eg Script, Notecard, Folder, etc - An array four bytes or longer - A signed integer, will be zero if the array contains - less than four bytes - - - Convert the first eight bytes of the given array in little endian - ordering to a signed long integer - - An array eight bytes or longer - A signed long integer, will be zero if the array contains - less than eight bytes + + Unknown - - - Convert the first eight bytes starting at the given position in - little endian ordering to a signed long integer - - An array eight bytes or longer - Position to start reading the long from - A signed long integer, will be zero if a long can't be read - at the given position + + Texture - - - Convert the first two bytes starting at the given position in - little endian ordering to an unsigned short - - Byte array containing the ushort - Position to start reading the ushort from - An unsigned short, will be zero if a ushort can't be read - at the given position + + Sound - - - Convert two bytes in little endian ordering to an unsigned short - - Byte array containing the ushort - An unsigned short, will be zero if a ushort can't be - read + + Calling Card - - - Convert the first four bytes starting at the given position in - little endian ordering to an unsigned integer - - Byte array containing the uint - Position to start reading the uint from - An unsigned integer, will be zero if a uint can't be read - at the given position + + Landmark - - - Convert the first four bytes of the given array in little endian - ordering to an unsigned integer - - An array four bytes or longer - An unsigned integer, will be zero if the array contains - less than four bytes + + Notecard - - - Convert the first eight bytes of the given array in little endian - ordering to an unsigned 64-bit integer - - An array eight bytes or longer - An unsigned 64-bit integer, will be zero if the array - contains less than eight bytes + + - - - Convert four bytes in little endian ordering to a floating point - value - - Byte array containing a little ending floating - point value - Starting position of the floating point value in - the byte array - Single precision value + + Folder - - - Convert an integer to a byte array in little endian format - - The integer to convert - A four byte little endian array + + - - - Convert an integer to a byte array in big endian format - - The integer to convert - A four byte big endian array + + an LSL Script - - - Convert a 64-bit integer to a byte array in little endian format - - The value to convert - An 8 byte little endian array + + - - - Convert a 64-bit unsigned integer to a byte array in little endian - format - - The value to convert - An 8 byte little endian array + + - - - Convert a floating point value to four bytes in little endian - ordering - - A floating point value - A four byte array containing the value in little endian - ordering + + - - - Converts an unsigned integer to a hexadecimal string - - An unsigned integer to convert to a string - A hexadecimal string 10 characters long - 0x7fffffff + + - - - Convert a variable length UTF8 byte array to a string - - The UTF8 encoded byte array to convert - The decoded string + + - - - Converts a byte array to a string containing hexadecimal characters - - The byte array to convert to a string - The name of the field to prepend to each - line of the string - A string containing hexadecimal characters on multiple - lines. Each line is prepended with the field name + + - + - Converts a byte array to a string containing hexadecimal characters + Item Sale Status - The byte array to convert to a string - Number of bytes in the array to parse - A string to prepend to each line of the hex - dump - A string containing hexadecimal characters on multiple - lines. Each line is prepended with the field name - - - Convert a string to a UTF8 encoded byte array - - The string to convert - A null-terminated UTF8 byte array + + Not for sale - - - Converts a string containing hexadecimal characters to a byte array - - String containing hexadecimal characters - If true, gracefully handles null, empty and - uneven strings as well as stripping unconvertable characters - The converted byte array + + The original is for sale - - - Returns true is c is a hexadecimal digit (A-F, a-f, 0-9) - - Character to test - true if hex digit, false if not + + Copies are for sale - - - Converts 1 or 2 character string into equivalant byte value - - 1 or 2 character string - byte + + The contents of the object are for sale - + - Convert a float value to a byte given a minimum and maximum range + Types of wearable assets - Value to convert to a byte - Minimum value range - Maximum value range - A single byte representing the original float value - - - Convert a byte to a float value given a minimum and maximum range - - Byte array to get the byte from - Position in the byte array the desired byte is at - Minimum value range - Maximum value range - A float value inclusively between lower and upper + + Body shape - - - Convert a byte to a float value given a minimum and maximum range - - Byte to convert to a float value - Minimum value range - Maximum value range - A float value inclusively between lower and upper + + Skin textures and attributes - + + Hair + + + Eyes + + + Shirt + + + Pants + + + Shoes + + + Socks + + + Jacket + + + Gloves + + + Undershirt + + + Underpants + + + Skirt + + + Alpha mask to hide parts of the avatar + + + Tattoo + + + Physics + + + Invalid wearable asset + + - Attempts to parse a floating point value from a string, using an - EN-US number format + Identifier code for primitive types - String to parse - Resulting floating point number - True if the parse was successful, otherwise false - + + None + + + A Primitive + + + A Avatar + + + Linden grass + + + Linden tree + + + A primitive that acts as the source for a particle stream + + + A Linden tree + + - Attempts to parse a floating point value from a string, using an - EN-US number format + Primary parameters for primitives such as Physics Enabled or Phantom - String to parse - Resulting floating point number - True if the parse was successful, otherwise false - - - Tries to parse an unsigned 32-bit integer from a hexadecimal string - - String to parse - Resulting integer - True if the parse was successful, otherwise false + + Deprecated + + + Whether physics are enabled for this object + + + + + + + + + + + + - - - Returns text specified in EnumInfo attribute of the enumerator - To add the text use [EnumInfo(Text = "Some nice text here")] before declaration - of enum values - - Enum value - Text representation of the enum + + - - - Takes an AssetType and returns the string representation - - The source - The string version of the AssetType + + - - - Translate a string name of an AssetType into the proper Type - - A string containing the AssetType name - The AssetType which matches the string name, or AssetType.Unknown if no match was found + + Whether this object contains an active touch script - - - Convert an InventoryType to a string - - The to convert - A string representation of the source + + - - - Convert a string into a valid InventoryType - - A string representation of the InventoryType to convert - A InventoryType object which matched the type + + Whether this object can receive payments - - - Convert a SaleType to a string - - The to convert - A string representation of the source + + Whether this object is phantom (no collisions) - - - Convert a string into a valid SaleType - - A string representation of the SaleType to convert - A SaleType object which matched the type + + - - - Converts a string used in LLSD to AttachmentPoint type - - String representation of AttachmentPoint to convert - AttachmentPoint enum + + - - - Copy a byte array - - Byte array to copy - A copy of the given byte array + + - - - Packs to 32-bit unsigned integers in to a 64-bit unsigned integer - - The left-hand (or X) value - The right-hand (or Y) value - A 64-bit integer containing the two 32-bit input values + + - - - Unpacks two 32-bit unsigned integers from a 64-bit unsigned integer - - The 64-bit input integer - The left-hand (or X) output value - The right-hand (or Y) output value + + Deprecated - - - Convert an IP address object to an unsigned 32-bit integer - - IP address to convert - 32-bit unsigned integer holding the IP address bits + + - - - Gets a unix timestamp for the current time - - An unsigned integer representing a unix timestamp for now + + - - - Convert a UNIX timestamp to a native DateTime object - - An unsigned integer representing a UNIX - timestamp - A DateTime object containing the same time specified in - the given timestamp + + - - - Convert a UNIX timestamp to a native DateTime object - - A signed integer representing a UNIX - timestamp - A DateTime object containing the same time specified in - the given timestamp + + Deprecated - - - Convert a native DateTime object to a UNIX timestamp - - A DateTime object you want to convert to a - timestamp - An unsigned integer representing a UNIX timestamp + + - - - Swap two values - - Type of the values to swap - First value - Second value + + - - - Try to parse an enumeration value from a string - - Enumeration type - String value to parse - Enumeration value on success - True if the parsing succeeded, otherwise false + + - - - Swaps the high and low words in a byte. Converts aaaabbbb to bbbbaaaa - - Byte to swap the words in - Byte value with the words swapped + + - - - Attempts to convert a string representation of a hostname or IP - address to a - - Hostname to convert to an IPAddress - Converted IP address object, or null if the conversion - failed + + Server flag, will not be sent to clients. Specifies that + the object is destroyed when it touches a simulator edge - - Provide a single instance of the CultureInfo class to - help parsing in situations where the grid assumes an en-us - culture + + Server flag, will not be sent to clients. Specifies that + the object will be returned to the owner's inventory when it + touches a simulator edge - - UNIX epoch in DateTime format + + Server flag, will not be sent to clients. - - Provide a single instance of the MD5 class to avoid making - duplicate copies and handle thread safety + + Server flag, will not be sent to client. Specifies that + the object is hovering/flying - - Provide a single instance of the SHA-1 class to avoid - making duplicate copies and handle thread safety + + - - Provide a single instance of a random number generator - to avoid making duplicate copies and handle thread safety + + - - - Clamp a given value between a range - - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper + + - - - Clamp a given value between a range - - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper + + - + - Clamp a given value between a range + Sound flags for sounds attached to primitives - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper - - - Round a floating-point value to the nearest integer - - Floating point number to round - Integer + + + + + + + + + + + + + + + + + + + + - + - Test if a single precision float is a finite number + Material type for a primitive - - - Test if a double precision float is a finite number - + + - - - Get the distance between two floating-point values - - First value - Second value - The distance between the two values + + - - - Compute the MD5 hash for a byte array - - Byte array to compute the hash for - MD5 hash of the input data + + - - - Compute the SHA1 hash for a byte array - - Byte array to compute the hash for - SHA1 hash of the input data + + - - - Calculate the SHA1 hash of a given string - - The string to hash - The SHA1 hash as a string + + - - - Compute the SHA256 hash for a byte array - - Byte array to compute the hash for - SHA256 hash of the input data + + - - - Calculate the SHA256 hash of a given string - - The string to hash - The SHA256 hash as a string + + - - - Calculate the MD5 hash of a given string - - The password to hash - An MD5 hash in string format, with $1$ prepended + + - + - Calculate the MD5 hash of a given string + Used in a helper function to roughly determine prim shape - The string to hash - The MD5 hash as a string - + - Generate a random double precision floating point value + Extra parameters for primitives, these flags are for features that have + been added after the original ObjectFlags that has all eight bits + reserved already - Random value of type double - - - Get the current running platform - - Enumeration of the current platform we are running on + + Whether this object has flexible parameters - + + Whether this object has light parameters + + + Whether this object is a sculpted prim + + + Whether this object is a light image map + + + Whether this object is a mesh + + - Get the current running runtime + - Enumeration of the current runtime we are running on - + + + + + + + + + + - Operating system + - - Unknown + + - - Microsoft Windows + + - - Microsoft Windows CE + + - - Linux + + - - Apple OSX + + - - - Runtime platform - + + - - .NET runtime + + - - Mono runtime: http://www.mono-project.com/ + + - + - Identifier code for primitive types + - - None + + - - A Primitive + + - - A Avatar + + - - Linden grass + + - - Linden tree + + - - A primitive that acts as the source for a particle stream + + - - A Linden tree + + - + + + + + + + - Primary parameters for primitives such as Physics Enabled or Phantom + - - Deprecated - - - Whether physics are enabled for this object + + - + - + - + - + - + - + - - Whether this object contains an active touch script + + + Attachment points for objects on avatar bodies + + + Both InventoryObject and InventoryAttachment types can be attached + + + + Right hand if object was not previously attached + + + Chest + + + Skull + + + Left shoulder + + + Right shoulder + + + Left hand + + + Right hand + + + Left foot + + + Right foot - - + + Spine - - Whether this object can receive payments + + Pelvis - - Whether this object is phantom (no collisions) + + Mouth - - + + Chin - - + + Left ear - - + + Right ear - - + + Left eyeball - - Deprecated + + Right eyeball - - + + Nose - - + + Right upper arm - - + + Right forearm - - Deprecated + + Left upper arm - - + + Left forearm - - + + Right hip - - + + Right upper leg - - + + Right lower leg - - Server flag, will not be sent to clients. Specifies that - the object is destroyed when it touches a simulator edge + + Left hip - - Server flag, will not be sent to clients. Specifies that - the object will be returned to the owner's inventory when it - touches a simulator edge + + Left upper leg - - Server flag, will not be sent to clients. + + Left lower leg - - Server flag, will not be sent to client. Specifies that - the object is hovering/flying + + Stomach - - + + Left pectoral - - + + Right pectoral - - + + HUD Center position 2 - - + + HUD Top-right - - - Sound flags for sounds attached to primitives - + + HUD Top - - + + HUD Top-left - - + + HUD Center - - + + HUD Bottom-left - - + + HUD Bottom - - + + HUD Bottom-right - - + + Neck - - + + Avatar Center - + - Material type for a primitive + Tree foliage types - - + + Pine1 tree - - + + Oak tree - - + + Tropical Bush1 - - + + Palm1 tree - - + + Dogwood tree - - + + Tropical Bush2 - - + + Palm2 tree - - + + Cypress1 tree - - - Used in a helper function to roughly determine prim shape - + + Cypress2 tree - - - Extra parameters for primitives, these flags are for features that have - been added after the original ObjectFlags that has all eight bits - reserved already - + + Pine2 tree - - Whether this object has flexible parameters + + Plumeria - - Whether this object has light parameters + + Winter pinetree1 - - Whether this object is a sculpted prim + + Winter Aspen tree - - Whether this object is a light image map + + Winter pinetree2 - - Whether this object is a mesh + + Eucalyptus tree - - - - + + Fern - - + + Eelgrass - - + + Sea Sword - - + + Kelp1 plant - + + Beach grass + + + Kelp2 plant + + - + Grass foliage types - + - + - + - + - + - + - - + + + Action associated with clicking on an object + + + + Touch object + + + Sit on object - - + + Purchase object or contents - - - - + + Pay the object - - + + Open task inventory - - + + Play parcel media - - + + Open parcel media - - + + + Type of physics representation used for this prim in the simulator + - - + + Use prim physics form this object - - + + No physics, prim doesn't collide - - + + Use convex hull represantion of this prim - - + + For thread safety - - + + For thread safety - + - + Purges expired objects from the cache. Called automatically by the purge timer. - - + + + A thread-safe lockless queue that supports multiple readers and + multiple writers + - - + + Queue head - - + + Queue tail - - + + Queue item count - - + + + Constructor + - - + + + Enqueue an item + + Item to enqeue - - + + + Try to dequeue an item + + Dequeued item if the dequeue was successful + True if an item was successfully deqeued, otherwise false - - - Attachment points for objects on avatar bodies - - - Both InventoryObject and InventoryAttachment types can be attached - + + Gets the current number of items in the queue. Since this + is a lockless collection this value should be treated as a close + estimate - - Right hand if object was not previously attached + + + Provides a node container for data in a singly linked list + - - Chest + + Pointer to the next node in list - - Skull + + The data contained by the node - - Left shoulder + + + Constructor + - - Right shoulder + + + Constructor + - - Left hand + + + Convert this matrix to euler rotations + + X euler angle + Y euler angle + Z euler angle - - Right hand + + + Convert this matrix to a quaternion rotation + + A quaternion representation of this rotation matrix - - Left foot + + + Construct a matrix from euler rotation values in radians + + X euler angle in radians + Y euler angle in radians + Z euler angle in radians - - Right foot + + + Get a formatted string representation of the vector + + A string representation of the vector - - Spine + + A 4x4 matrix containing all zeroes - - Pelvis + + A 4x4 identity matrix - - Mouth + + X value - - Chin + + Y value - - Left ear + + Z value - - Right ear + + W value - - Left eyeball + + + Build a quaternion from normalized float values + + X value from -1.0 to 1.0 + Y value from -1.0 to 1.0 + Z value from -1.0 to 1.0 - - Right eyeball + + + Constructor, builds a quaternion object from a byte array + + Byte array containing four four-byte floats + Offset in the byte array to start reading at + Whether the source data is normalized or + not. If this is true 12 bytes will be read, otherwise 16 bytes will + be read. - - Nose + + + Normalizes the quaternion + - - Right upper arm + + + Builds a quaternion object from a byte array + + The source byte array + Offset in the byte array to start reading at + Whether the source data is normalized or + not. If this is true 12 bytes will be read, otherwise 16 bytes will + be read. - - Right forearm + + + Normalize this quaternion and serialize it to a byte array + + A 12 byte array containing normalized X, Y, and Z floating + point values in order using little endian byte ordering - - Left upper arm + + + Writes the raw bytes for this quaternion to a byte array + + Destination byte array + Position in the destination array to start + writing. Must be at least 12 bytes before the end of the array - - Left forearm + + + Convert this quaternion to euler angles + + X euler angle + Y euler angle + Z euler angle - - Right hip + + + Convert this quaternion to an angle around an axis + + Unit vector describing the axis + Angle around the axis, in radians - - Right upper leg + + + Returns the conjugate (spatial inverse) of a quaternion + - - Right lower leg + + + Build a quaternion from an axis and an angle of rotation around + that axis + - - Left hip + + + Build a quaternion from an axis and an angle of rotation around + that axis + + Axis of rotation + Angle of rotation - - Left upper leg + + + Creates a quaternion from a vector containing roll, pitch, and yaw + in radians + + Vector representation of the euler angles in + radians + Quaternion representation of the euler angles - - Left lower leg + + + Creates a quaternion from roll, pitch, and yaw euler angles in + radians + + X angle in radians + Y angle in radians + Z angle in radians + Quaternion representation of the euler angles - - Stomach + + + Conjugates and renormalizes a vector + - - Left pectoral + + + Spherical linear interpolation between two quaternions + - - Right pectoral + + + Get a string representation of the quaternion elements with up to three + decimal digits and separated by spaces only + + Raw string representation of the quaternion - - HUD Center position 2 + + A quaternion with a value of 0,0,0,1 - - HUD Top-right + + + Determines the appropriate events to set, leaves the locks, and sets the events. + - - HUD Top + + + A routine for lazily creating a event outside the lock (so if errors + happen they are outside the lock and that we don't do much work + while holding a spin lock). If all goes well, reenter the lock and + set 'waitEvent' + - - HUD Top-left + + + Waits on 'waitEvent' with a timeout of 'millisceondsTimeout. + Before the wait 'numWaiters' is incremented and is restored before leaving this routine. + - - HUD Center + + + A hierarchical token bucket for bandwidth throttling. See + http://en.wikipedia.org/wiki/Token_bucket for more information + - - HUD Bottom-left + + Parent bucket to this bucket, or null if this is a root + bucket - - HUD Bottom + + Size of the bucket in bytes. If zero, the bucket has + infinite capacity - - HUD Bottom-right + + Rate that the bucket fills, in bytes per millisecond. If + zero, the bucket always remains full - - Neck + + Number of tokens currently in the bucket - - Avatar Center + + Time of the last drip, in system ticks - + - Tree foliage types + Default constructor + Parent bucket if this is a child bucket, or + null if this is a root bucket + Maximum size of the bucket in bytes, or + zero if this bucket has no maximum capacity + Rate that the bucket fills, in bytes per + second. If zero, the bucket always remains full - - Pine1 tree + + + Remove a given number of tokens from the bucket + + Number of tokens to remove from the bucket + True if the requested number of tokens were removed from + the bucket, otherwise false - - Oak tree + + + Remove a given number of tokens from the bucket + + Number of tokens to remove from the bucket + True if tokens were added to the bucket + during this call, otherwise false + True if the requested number of tokens were removed from + the bucket, otherwise false - - Tropical Bush1 + + + Add tokens to the bucket over time. The number of tokens added each + call depends on the length of time that has passed since the last + call to Drip + + True if tokens were added to the bucket, otherwise false - - Palm1 tree + + + The parent bucket of this bucket, or null if this bucket has no + parent. The parent bucket will limit the aggregate bandwidth of all + of its children buckets + - - Dogwood tree + + + Maximum burst rate in bytes per second. This is the maximum number + of tokens that can accumulate in the bucket at any one time + - - Tropical Bush2 + + + The speed limit of this bucket in bytes per second. This is the + number of tokens that are added to the bucket per second + + Tokens are added to the bucket any time + is called, at the granularity of + the system tick interval (typically around 15-22ms) - - Palm2 tree + + + The number of bytes that can be sent at this moment. This is the + current number of tokens in the bucket + If this bucket has a parent bucket that does not have + enough tokens for a request, will + return false regardless of the content of this bucket + - - Cypress1 tree + + Used for converting degrees to radians - - Cypress2 tree + + Used for converting radians to degrees - - Pine2 tree + + Provide a single instance of the CultureInfo class to + help parsing in situations where the grid assumes an en-us + culture - - Plumeria + + UNIX epoch in DateTime format - - Winter pinetree1 + + Provide a single instance of the MD5 class to avoid making + duplicate copies and handle thread safety - - Winter Aspen tree + + Provide a single instance of the SHA-1 class to avoid + making duplicate copies and handle thread safety - - Winter pinetree2 + + Provide a single instance of a random number generator + to avoid making duplicate copies and handle thread safety - - Eucalyptus tree + + + Clamp a given value between a range + + Value to clamp + Minimum allowable value + Maximum allowable value + A value inclusively between lower and upper - - Fern + + + Clamp a given value between a range + + Value to clamp + Minimum allowable value + Maximum allowable value + A value inclusively between lower and upper - - Eelgrass + + + Clamp a given value between a range + + Value to clamp + Minimum allowable value + Maximum allowable value + A value inclusively between lower and upper - - Sea Sword + + + Round a floating-point value to the nearest integer + + Floating point number to round + Integer - - Kelp1 plant + + + Test if a single precision float is a finite number + - - Beach grass + + + Test if a double precision float is a finite number + - - Kelp2 plant + + + Get the distance between two floating-point values + + First value + Second value + The distance between the two values - + - Grass foliage types + Compute the MD5 hash for a byte array + Byte array to compute the hash for + MD5 hash of the input data - - + + + Compute the SHA1 hash for a byte array + + Byte array to compute the hash for + SHA1 hash of the input data - - + + + Calculate the SHA1 hash of a given string + + The string to hash + The SHA1 hash as a string - - + + + Compute the SHA256 hash for a byte array + + Byte array to compute the hash for + SHA256 hash of the input data - - + + + Calculate the SHA256 hash of a given string + + The string to hash + The SHA256 hash as a string - - + + + Calculate the MD5 hash of a given string + + The password to hash + An MD5 hash in string format, with $1$ prepended - - + + + Calculate the MD5 hash of a given string + + The string to hash + The MD5 hash as a string - + - Action associated with clicking on an object + Generate a random double precision floating point value + Random value of type double - - Touch object + + + Get the current running platform + + Enumeration of the current platform we are running on - - Sit on object + + + Get the current running runtime + + Enumeration of the current runtime we are running on - - Purchase object or contents + + + Convert the first two bytes starting in the byte array in + little endian ordering to a signed short integer + + An array two bytes or longer + A signed short integer, will be zero if a short can't be + read at the given position - - Pay the object + + + Convert the first two bytes starting at the given position in + little endian ordering to a signed short integer + + An array two bytes or longer + Position in the array to start reading + A signed short integer, will be zero if a short can't be + read at the given position - - Open task inventory + + + Convert the first four bytes starting at the given position in + little endian ordering to a signed integer + + An array four bytes or longer + Position to start reading the int from + A signed integer, will be zero if an int can't be read + at the given position - - Play parcel media + + + Convert the first four bytes of the given array in little endian + ordering to a signed integer + + An array four bytes or longer + A signed integer, will be zero if the array contains + less than four bytes - - Open parcel media + + + Convert the first eight bytes of the given array in little endian + ordering to a signed long integer + + An array eight bytes or longer + A signed long integer, will be zero if the array contains + less than eight bytes - + - Type of physics representation used for this prim in the simulator + Convert the first eight bytes starting at the given position in + little endian ordering to a signed long integer + An array eight bytes or longer + Position to start reading the long from + A signed long integer, will be zero if a long can't be read + at the given position - - Use prim physics form this object + + + Convert the first two bytes starting at the given position in + little endian ordering to an unsigned short + + Byte array containing the ushort + Position to start reading the ushort from + An unsigned short, will be zero if a ushort can't be read + at the given position - - No physics, prim doesn't collide + + + Convert two bytes in little endian ordering to an unsigned short + + Byte array containing the ushort + An unsigned short, will be zero if a ushort can't be + read - - Use convex hull represantion of this prim + + + Convert the first four bytes starting at the given position in + little endian ordering to an unsigned integer + + Byte array containing the uint + Position to start reading the uint from + An unsigned integer, will be zero if a uint can't be read + at the given position - - X value + + + Convert the first four bytes of the given array in little endian + ordering to an unsigned integer + + An array four bytes or longer + An unsigned integer, will be zero if the array contains + less than four bytes - - Y value + + + Convert the first eight bytes of the given array in little endian + ordering to an unsigned 64-bit integer + + An array eight bytes or longer + An unsigned 64-bit integer, will be zero if the array + contains less than eight bytes - - Z value + + + Convert four bytes in little endian ordering to a floating point + value + + Byte array containing a little ending floating + point value + Starting position of the floating point value in + the byte array + Single precision value - - W value + + + Convert an integer to a byte array in little endian format + + The integer to convert + A four byte little endian array - + - Constructor, builds a vector from a byte array + Convert an integer to a byte array in big endian format - Byte array containing four four-byte floats - Beginning position in the byte array + The integer to convert + A four byte big endian array - + - Test if this vector is equal to another vector, within a given - tolerance range + Convert a 64-bit integer to a byte array in little endian format - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false + The value to convert + An 8 byte little endian array - + - IComparable.CompareTo implementation + Convert a 64-bit unsigned integer to a byte array in little endian + format + The value to convert + An 8 byte little endian array - + - Test if this vector is composed of all finite numbers + Convert a floating point value to four bytes in little endian + ordering + A floating point value + A four byte array containing the value in little endian + ordering - + - Builds a vector from a byte array + Converts an unsigned integer to a hexadecimal string - Byte array containing a 16 byte vector - Beginning position in the byte array + An unsigned integer to convert to a string + A hexadecimal string 10 characters long + 0x7fffffff - + - Returns the raw bytes for this vector + Convert a variable length UTF8 byte array to a string - A 16 byte array containing X, Y, Z, and W + The UTF8 encoded byte array to convert + The decoded string - + - Writes the raw bytes for this vector to a byte array + Converts a byte array to a string containing hexadecimal characters - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array + The byte array to convert to a string + The name of the field to prepend to each + line of the string + A string containing hexadecimal characters on multiple + lines. Each line is prepended with the field name - + - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only + Converts a byte array to a string containing hexadecimal characters - Raw string representation of the vector - - - A vector with a value of 0,0,0,0 - - - A vector with a value of 1,1,1,1 - - - A vector with a value of 1,0,0,0 - - - A vector with a value of 0,1,0,0 - - - A vector with a value of 0,0,1,0 - - - A vector with a value of 0,0,0,1 + The byte array to convert to a string + Number of bytes in the array to parse + A string to prepend to each line of the hex + dump + A string containing hexadecimal characters on multiple + lines. Each line is prepended with the field name - + - An 8-bit color structure including an alpha channel + Convert a string to a UTF8 encoded byte array + The string to convert + A null-terminated UTF8 byte array - - Red - - - Green - - - Blue - - - Alpha - - + - + Converts a string containing hexadecimal characters to a byte array - - - - + String containing hexadecimal characters + If true, gracefully handles null, empty and + uneven strings as well as stripping unconvertable characters + The converted byte array - + - Builds a color from a byte array + Returns true is c is a hexadecimal digit (A-F, a-f, 0-9) - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 + Character to test + true if hex digit, false if not - + - Returns the raw bytes for this vector + Converts 1 or 2 character string into equivalant byte value - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 - True if the alpha value is inverted in - addition to whatever the inverted parameter is. Setting inverted true - and alphaInverted true will flip the alpha value back to non-inverted, - but keep the other color bytes inverted - A 16 byte array containing R, G, B, and A + 1 or 2 character string + byte - + - Copy constructor + Convert a float value to a byte given a minimum and maximum range - Color to copy + Value to convert to a byte + Minimum value range + Maximum value range + A single byte representing the original float value - + - IComparable.CompareTo implementation + Convert a byte to a float value given a minimum and maximum range - Sorting ends up like this: |--Grayscale--||--Color--|. - Alpha is only used when the colors are otherwise equivalent + Byte array to get the byte from + Position in the byte array the desired byte is at + Minimum value range + Maximum value range + A float value inclusively between lower and upper - + - Builds a color from a byte array + Convert a byte to a float value given a minimum and maximum range - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 - True if the alpha value is inverted in - addition to whatever the inverted parameter is. Setting inverted true - and alphaInverted true will flip the alpha value back to non-inverted, - but keep the other color bytes inverted + Byte to convert to a float value + Minimum value range + Maximum value range + A float value inclusively between lower and upper - + - Writes the raw bytes for this color to a byte array + Attempts to parse a floating point value from a string, using an + EN-US number format - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array + String to parse + Resulting floating point number + True if the parse was successful, otherwise false - + - Serializes this color into four bytes in a byte array + Attempts to parse a floating point value from a string, using an + EN-US number format - Destination byte array - Position in the destination array to start - writing. Must be at least 4 bytes before the end of the array - True to invert the output (1.0 becomes 0 - instead of 255) + String to parse + Resulting floating point number + True if the parse was successful, otherwise false - + - Writes the raw bytes for this color to a byte array + Tries to parse an unsigned 32-bit integer from a hexadecimal string - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array + String to parse + Resulting integer + True if the parse was successful, otherwise false - + - Ensures that values are in range 0-1 + Returns text specified in EnumInfo attribute of the enumerator + To add the text use [EnumInfo(Text = "Some nice text here")] before declaration + of enum values + Enum value + Text representation of the enum - + - Create an RGB color from a hue, saturation, value combination + Takes an AssetType and returns the string representation - Hue - Saturation - Value - An fully opaque RGB color (alpha is 1.0) + The source + The string version of the AssetType - + - Performs linear interpolation between two colors + Translate a string name of an AssetType into the proper Type - Color to start at - Color to end at - Amount to interpolate - The interpolated color - - - A Color4 with zero RGB values and fully opaque (alpha 1.0) - - - A Color4 with full RGB values (1.0) and fully opaque (alpha 1.0) + A string containing the AssetType name + The AssetType which matches the string name, or AssetType.Unknown if no match was found - + - Copy constructor + Convert an InventoryType to a string - Circular queue to copy + The to convert + A string representation of the source - + - A three-dimensional vector with floating-point values + Convert a string into a valid InventoryType + A string representation of the InventoryType to convert + A InventoryType object which matched the type - - X value - - - Y value + + + Convert a SaleType to a string + + The to convert + A string representation of the source - - Z value + + + Convert a string into a valid SaleType + + A string representation of the SaleType to convert + A SaleType object which matched the type - + - Constructor, builds a vector from a byte array + Converts a string used in LLSD to AttachmentPoint type - Byte array containing three four-byte floats - Beginning position in the byte array + String representation of AttachmentPoint to convert + AttachmentPoint enum - + - Test if this vector is equal to another vector, within a given - tolerance range + Copy a byte array - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false + Byte array to copy + A copy of the given byte array - + - IComparable.CompareTo implementation + Packs to 32-bit unsigned integers in to a 64-bit unsigned integer + The left-hand (or X) value + The right-hand (or Y) value + A 64-bit integer containing the two 32-bit input values - + - Test if this vector is composed of all finite numbers + Unpacks two 32-bit unsigned integers from a 64-bit unsigned integer + The 64-bit input integer + The left-hand (or X) output value + The right-hand (or Y) output value - + - Builds a vector from a byte array + Convert an IP address object to an unsigned 32-bit integer - Byte array containing a 12 byte vector - Beginning position in the byte array + IP address to convert + 32-bit unsigned integer holding the IP address bits - + - Returns the raw bytes for this vector + Gets a unix timestamp for the current time - A 12 byte array containing X, Y, and Z + An unsigned integer representing a unix timestamp for now - + - Writes the raw bytes for this vector to a byte array + Convert a UNIX timestamp to a native DateTime object - Destination byte array - Position in the destination array to start - writing. Must be at least 12 bytes before the end of the array + An unsigned integer representing a UNIX + timestamp + A DateTime object containing the same time specified in + the given timestamp - + - Parse a vector from a string + Convert a UNIX timestamp to a native DateTime object - A string representation of a 3D vector, enclosed - in arrow brackets and separated by commas + A signed integer representing a UNIX + timestamp + A DateTime object containing the same time specified in + the given timestamp - + - Calculate the rotation between two vectors + Convert a native DateTime object to a UNIX timestamp - Normalized directional vector (such as 1,0,0 for forward facing) - Normalized target vector + A DateTime object you want to convert to a + timestamp + An unsigned integer representing a UNIX timestamp - + - Interpolates between two vectors using a cubic equation + Swap two values + Type of the values to swap + First value + Second value - + - Get a formatted string representation of the vector + Try to parse an enumeration value from a string - A string representation of the vector + Enumeration type + String value to parse + Enumeration value on success + True if the parsing succeeded, otherwise false - + - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only + Swaps the high and low words in a byte. Converts aaaabbbb to bbbbaaaa - Raw string representation of the vector + Byte to swap the words in + Byte value with the words swapped - + - Cross product between two vectors + Attempts to convert a string representation of a hostname or IP + address to a + Hostname to convert to an IPAddress + Converted IP address object, or null if the conversion + failed - + - Explicit casting for Vector3d > Vector3 + Operating system - - - - A vector with a value of 0,0,0 + + Unknown - - A vector with a value of 1,1,1 + + Microsoft Windows - - A unit vector facing forward (X axis), value 1,0,0 + + Microsoft Windows CE - - A unit vector facing left (Y axis), value 0,1,0 + + Linux - - A unit vector facing up (Z axis), value 0,0,1 + + Apple OSX + + + + Runtime platform + + + + .NET runtime + + + Mono runtime: http://www.mono-project.com/ @@ -2063,118 +2164,26 @@ True if the UUIDs are not equal, otherwise true - - XOR operator - - First UUID - Second UUID - A UUID that is a XOR combination of the two input UUIDs - - - - String typecasting operator - - A UUID in string form. Case insensitive, - hyphenated or non-hyphenated - A UUID built from the string representation - - - An UUID with a value of all zeroes - - - A cache of UUID.Zero as a string to optimize a common path - - - - A hierarchical token bucket for bandwidth throttling. See - http://en.wikipedia.org/wiki/Token_bucket for more information - - - - Parent bucket to this bucket, or null if this is a root - bucket - - - Size of the bucket in bytes. If zero, the bucket has - infinite capacity - - - Rate that the bucket fills, in bytes per millisecond. If - zero, the bucket always remains full - - - Number of tokens currently in the bucket - - - Time of the last drip, in system ticks - - - - Default constructor - - Parent bucket if this is a child bucket, or - null if this is a root bucket - Maximum size of the bucket in bytes, or - zero if this bucket has no maximum capacity - Rate that the bucket fills, in bytes per - second. If zero, the bucket always remains full - - - - Remove a given number of tokens from the bucket - - Number of tokens to remove from the bucket - True if the requested number of tokens were removed from - the bucket, otherwise false - - - - Remove a given number of tokens from the bucket - - Number of tokens to remove from the bucket - True if tokens were added to the bucket - during this call, otherwise false - True if the requested number of tokens were removed from - the bucket, otherwise false - - - - Add tokens to the bucket over time. The number of tokens added each - call depends on the length of time that has passed since the last - call to Drip - - True if tokens were added to the bucket, otherwise false - - - - The parent bucket of this bucket, or null if this bucket has no - parent. The parent bucket will limit the aggregate bandwidth of all - of its children buckets - - - - - Maximum burst rate in bytes per second. This is the maximum number - of tokens that can accumulate in the bucket at any one time - - - - - The speed limit of this bucket in bytes per second. This is the - number of tokens that are added to the bucket per second + + XOR operator - Tokens are added to the bucket any time - is called, at the granularity of - the system tick interval (typically around 15-22ms) + First UUID + Second UUID + A UUID that is a XOR combination of the two input UUIDs - + - The number of bytes that can be sent at this moment. This is the - current number of tokens in the bucket - If this bucket has a parent bucket that does not have - enough tokens for a request, will - return false regardless of the content of this bucket + String typecasting operator + A UUID in string form. Case insensitive, + hyphenated or non-hyphenated + A UUID built from the string representation + + + An UUID with a value of all zeroes + + + A cache of UUID.Zero as a string to optimize a common path @@ -2266,337 +2275,328 @@ A vector with a value of 0,1 - + - Attribute class that allows extra attributes to be attached to ENUMs + A three-dimensional vector with floating-point values - - Text used when presenting ENUM to user + + X value - - Default initializer + + Y value - - Text used when presenting ENUM to user + + Z value - + - The different types of grid assets + Constructor, builds a vector from a byte array + Byte array containing three four-byte floats + Beginning position in the byte array - - Unknown asset type - - - Texture asset, stores in JPEG2000 J2C stream format - - - Sound asset - - - Calling card for another avatar - - - Link to a location in world - - - Collection of textures and parameters that can be - worn by an avatar - - - Primitive that can contain textures, sounds, - scripts and more - - - Notecard asset - - - Holds a collection of inventory items - - - Root inventory folder - - - Linden scripting language script - - - LSO bytecode for a script - - - Uncompressed TGA texture - - - Collection of textures and shape parameters that can - be worn - - - Trash folder - - - Snapshot folder - - - Lost and found folder - - - Uncompressed sound - - - Uncompressed TGA non-square image, not to be used as a - texture - - - Compressed JPEG non-square image, not to be used as a - texture - - - Animation - - - Sequence of animations, sounds, chat, and pauses - - - Simstate file - - - Contains landmarks for favorites - - - Asset is a link to another inventory item - - - Asset is a link to another inventory folder - - - Beginning of the range reserved for ensembles - - - End of the range reserved for ensembles - - - Folder containing inventory links to wearables and attachments - that are part of the current outfit - - - Folder containing inventory items or links to - inventory items of wearables and attachments - together make a full outfit - - - Root folder for the folders of type OutfitFolder - - - Linden mesh format - - - Marketplace direct delivery inbox ("Received Items") - - - Marketplace direct delivery outbox - - - - - + - Inventory Item Types, eg Script, Notecard, Folder, etc + Test if this vector is equal to another vector, within a given + tolerance range + Vector to test against + The acceptable magnitude of difference + between the two vectors + True if the magnitude of difference between the two vectors + is less than the given tolerance, otherwise false - - Unknown - - - Texture - - - Sound - - - Calling Card - - - Landmark - - - Notecard - - - - - - Folder + + + IComparable.CompareTo implementation + - - + + + Test if this vector is composed of all finite numbers + - - an LSL Script + + + Builds a vector from a byte array + + Byte array containing a 12 byte vector + Beginning position in the byte array - - + + + Returns the raw bytes for this vector + + A 12 byte array containing X, Y, and Z - - + + + Writes the raw bytes for this vector to a byte array + + Destination byte array + Position in the destination array to start + writing. Must be at least 12 bytes before the end of the array - - + + + Parse a vector from a string + + A string representation of a 3D vector, enclosed + in arrow brackets and separated by commas - - + + + Calculate the rotation between two vectors + + Normalized directional vector (such as 1,0,0 for forward facing) + Normalized target vector - - + + + Interpolates between two vectors using a cubic equation + - - + + + Get a formatted string representation of the vector + + A string representation of the vector - + - Item Sale Status + Get a string representation of the vector elements with up to three + decimal digits and separated by spaces only + Raw string representation of the vector - - Not for sale - - - The original is for sale - - - Copies are for sale - - - The contents of the object are for sale + + + Cross product between two vectors + - + - Types of wearable assets + Explicit casting for Vector3d > Vector3 + + - - Body shape + + A vector with a value of 0,0,0 - - Skin textures and attributes + + A vector with a value of 1,1,1 - - Hair + + A unit vector facing forward (X axis), value 1,0,0 - - Eyes + + A unit vector facing left (Y axis), value 0,1,0 - - Shirt + + A unit vector facing up (Z axis), value 0,0,1 - - Pants + + + A three-dimensional vector with doubleing-point values + - - Shoes + + X value - - Socks + + Y value - - Jacket + + Z value - - Gloves + + + Constructor, builds a vector from a byte array + + Byte array containing three eight-byte doubles + Beginning position in the byte array - - Undershirt + + + Test if this vector is equal to another vector, within a given + tolerance range + + Vector to test against + The acceptable magnitude of difference + between the two vectors + True if the magnitude of difference between the two vectors + is less than the given tolerance, otherwise false - - Underpants + + + IComparable.CompareTo implementation + - - Skirt + + + Test if this vector is composed of all finite numbers + - - Alpha mask to hide parts of the avatar + + + Builds a vector from a byte array + + Byte array containing a 24 byte vector + Beginning position in the byte array - - Tattoo + + + Returns the raw bytes for this vector + + A 24 byte array containing X, Y, and Z - - Physics + + + Writes the raw bytes for this vector to a byte array + + Destination byte array + Position in the destination array to start + writing. Must be at least 24 bytes before the end of the array - - Invalid wearable asset + + + Parse a vector from a string + + A string representation of a 3D vector, enclosed + in arrow brackets and separated by commas - + - Same as Queue except Dequeue function blocks until there is an object to return. - Note: This class does not need to be synchronized + Interpolates between two vectors using a cubic equation - + - Create new BlockingQueue. + Get a formatted string representation of the vector - The System.Collections.ICollection to copy elements from + A string representation of the vector - + - Create new BlockingQueue. + Get a string representation of the vector elements with up to three + decimal digits and separated by spaces only - The initial number of elements that the queue can contain + Raw string representation of the vector - + - Create new BlockingQueue. + Cross product between two vectors - + - BlockingQueue Destructor (Close queue, resume any waiting thread). + Implicit casting for Vector3 > Vector3d + + - + + A vector with a value of 0,0,0 + + + A vector with a value of 1,1,1 + + + A unit vector facing forward (X axis), value of 1,0,0 + + + A unit vector facing left (Y axis), value of 0,1,0 + + + A unit vector facing up (Z axis), value of 0,0,1 + + + X value + + + Y value + + + Z value + + + W value + + - Remove all objects from the Queue. + Constructor, builds a vector from a byte array + Byte array containing four four-byte floats + Beginning position in the byte array - + - Remove all objects from the Queue, resume all dequeue threads. + Test if this vector is equal to another vector, within a given + tolerance range + Vector to test against + The acceptable magnitude of difference + between the two vectors + True if the magnitude of difference between the two vectors + is less than the given tolerance, otherwise false - + - Removes and returns the object at the beginning of the Queue. + IComparable.CompareTo implementation - Object in queue. - + - Removes and returns the object at the beginning of the Queue. + Test if this vector is composed of all finite numbers - time to wait before returning - Object in queue. - + - Removes and returns the object at the beginning of the Queue. + Builds a vector from a byte array - time to wait before returning (in milliseconds) - Object in queue. + Byte array containing a 16 byte vector + Beginning position in the byte array - + - Adds an object to the end of the Queue + Returns the raw bytes for this vector - Object to put in queue + A 16 byte array containing X, Y, Z, and W - + - Open Queue. + Writes the raw bytes for this vector to a byte array + Destination byte array + Position in the destination array to start + writing. Must be at least 16 bytes before the end of the array - + - Gets flag indicating if queue has been closed. + Get a string representation of the vector elements with up to three + decimal digits and separated by spaces only + Raw string representation of the vector + + + A vector with a value of 0,0,0,0 + + + A vector with a value of 1,1,1,1 + + + A vector with a value of 1,0,0,0 + + + A vector with a value of 0,1,0,0 + + + A vector with a value of 0,0,1,0 + + + A vector with a value of 0,0,0,1 diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll index c600076..ceea86b 100755 Binary files a/bin/OpenMetaverseTypes.dll and b/bin/OpenMetaverseTypes.dll differ -- cgit v1.1 From cb586d11582fa2641fe99edc6367edc800af0ba0 Mon Sep 17 00:00:00 2001 From: AliciaRaven Date: Mon, 4 May 2015 04:10:08 +0100 Subject: Enable grab feature (Ctrl+Drag) for non-physical link-sets and add code to handle spin (Ctrl+Shift+Drag) This patch fixes permission issues with dragging scripted objects. As on LL grid, scripted prims can not be dragged. Also after dragging, the group was not marked as updated. This meant that after the region was restarted the group would revert to its original position. This version fixes issues where scripts in child prims were not detected and also blocks grab for attachments. Signed-off-by: BlueWall --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 30 +++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 0a1a226..866a43c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2672,20 +2672,27 @@ namespace OpenSim.Region.Framework.Scenes } else { - //NonPhysicalGrabMovement(pos); + NonPhysicalGrabMovement(pos); } } else { - //NonPhysicalGrabMovement(pos); + NonPhysicalGrabMovement(pos); } } } + /// + /// Apply possition for grabbing non-physical linksets (Ctrl+Drag) + /// This MUST be blocked for linksets that contain touch scripts because the viewer triggers grab on the touch + /// event (Viewer Bug?) This would allow anyone to drag a linkset with a touch script. SL behaviour is also to + /// block grab on prims with touch events. + /// + /// New Position public void NonPhysicalGrabMovement(Vector3 pos) { - AbsolutePosition = pos; - m_rootPart.SendTerseUpdateToAllClients(); + if(!IsAttachment && ScriptCount() == 0) + UpdateGroupPosition(pos); } /// @@ -2781,17 +2788,28 @@ namespace OpenSim.Region.Framework.Scenes } else { - //NonPhysicalSpinMovement(pos); + NonPhysicalSpinMovement(newOrientation); } } else { - //NonPhysicalSpinMovement(pos); + NonPhysicalSpinMovement(newOrientation); } } } /// + /// Apply rotation for spinning non-physical linksets (Ctrl+Shift+Drag) + /// As with dragging, scripted objects must be blocked from spinning + /// + /// New Rotation + private void NonPhysicalSpinMovement(Quaternion newOrientation) + { + if(!IsAttachment && ScriptCount() == 0) + UpdateGroupRotationR(newOrientation); + } + + /// /// Set the name of a prim /// /// -- cgit v1.1 From 3c2886cd7507890b03f1213ca280c4a505af52c3 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Wed, 13 May 2015 14:31:28 -0500 Subject: Adding back command to clear region's user cache --- .../UserManagement/UserManagementModule.cs | 29 ++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index ba71dc5..7ecbd26 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement #endregion ISharedRegionModule - + #region Event Handlers void EventManager_OnPrimsLoaded(Scene s) @@ -180,7 +180,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement void HandleUUIDNameRequest(UUID uuid, IClientAPI client) { // m_log.DebugFormat( -// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}", +// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}", // uuid, remote_client.Name); if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) @@ -212,7 +212,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement // appear to clear this when the user asks it to clear the cache, but others may not. // // So to avoid clients - // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will + // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will // instead drop the request entirely. if (GetUser(uuid, out user)) { @@ -220,7 +220,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement } // else // m_log.DebugFormat( -// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}", +// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}", // uuid, client.Name); }); } @@ -416,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement m_log.Debug("[USER MANAGEMENT MODULE]: GetServerURLs call failed ", e); userdata.ServerURLs = new Dictionary(); } - + if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) return userdata.ServerURLs[serverType].ToString(); } @@ -620,7 +620,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement AddUser(id, string.Empty, string.Empty, string.Empty); } else - { + { string homeURL; string firstname = string.Empty; string lastname = string.Empty; @@ -676,7 +676,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement else { lock(m_UserCache) - { + { if(!m_UserCache.ContainsKey(id)) { UserData newUser = new UserData(); @@ -726,6 +726,21 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement "Show the bindings between user UUIDs and user names", String.Empty, HandleShowUsers); + + MainConsole.Instance.Commands.AddCommand("Users", true, + "reset user cache", + "reset user cache", + "reset user cache to allow changed settings to be applied", + String.Empty, + HandleResetUserCache); + } + + private void HandleResetUserCache(string module, string[] cmd) + { + lock(m_UserCache) + { + m_UserCache.Clear(); + } } private void HandleShowUser(string module, string[] cmd) -- cgit v1.1 From 6a48c87cd20e9df5ebdd2898872618455106be4c Mon Sep 17 00:00:00 2001 From: dahlia Date: Wed, 13 May 2015 15:59:58 -0700 Subject: resolve possible nullref when sending appearance packet. Thanks to zadark for pointing this out. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 855342f..284c5fa 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3747,6 +3747,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; + avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0]; //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); OutPacket(avp, ThrottleOutPacketType.Task); } -- cgit v1.1 From 946a6622fe58da47bc031574937085be4e3c5511 Mon Sep 17 00:00:00 2001 From: Michael Heilmann Date: Tue, 19 May 2015 15:52:13 -0400 Subject: Removing duplicate definition --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 905bde2..7913f42 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -64,8 +64,6 @@ namespace OpenSim.Region.Framework.Scenes public const int m_defaultNumberFramesStored = 10; - public const int m_defaultNumberFramesStored = 10; - public delegate void SynchronizeSceneHandler(Scene scene); #region Fields -- cgit v1.1 From d9afe354ac90c9a9b75f2ff05f3b8180225334fb Mon Sep 17 00:00:00 2001 From: Talun Date: Tue, 19 May 2015 19:07:48 +0100 Subject: New values returned by llGetEnv Implements recent changes to llGetEnv region_cpu_ratio hardcoded to 1 region_product_sku hardcoded to OpenSim Signed-off-by: Michael Cerquoni --- OpenSim/Region/Framework/Scenes/Scene.cs | 8 ++++- .../Shared/Api/Implementation/LSL_Api.cs | 34 +++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 906c862..643dca3 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -454,6 +454,12 @@ namespace OpenSim.Region.Framework.Scenes private string m_defaultScriptEngine; + private int m_unixStartTime; + public int UnixStartTime + { + get { return m_unixStartTime; } + } + /// /// Tick at which the last login occurred. /// @@ -1438,7 +1444,7 @@ namespace OpenSim.Region.Framework.Scenes m_isRunning = true; m_active = true; - + m_unixStartTime = Util.UnixTimeSinceEpoch(); // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); if (m_heartbeatThread != null) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 089a5a8..8359440 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5785,7 +5785,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String llGetEnv(LSL_String name) { m_host.AddScriptLPS(1); - if (name == "dynamic_pathfinding") + if (name == "agent_limit") + { + return World.RegionInfo.RegionSettings.AgentLimit.ToString(); + } + else if (name == "dynamic_pathfinding") { return "0"; } @@ -5793,14 +5797,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { return World.RegionInfo.EstateSettings.EstateID.ToString(); } + else if (name == "estate_name") + { + return World.RegionInfo.EstateSettings.EstateName; + } else if (name == "frame_number") { return World.Frame.ToString(); } + else if (name == "region_cpu_ratio") + { + return "1"; + } else if (name == "region_idle") { return "0"; } + else if (name == "region_product_name") + { + if (World.RegionInfo.RegionType != String.Empty) + return World.RegionInfo.RegionType; + else + return ""; + } + else if (name == "region_product_sku") + { + return "OpenSim"; + } + else if (name == "region_start_time") + { + return World.UnixStartTime.ToString(); + } else if (name == "sim_channel") { return "OpenSim"; @@ -5809,6 +5836,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { return World.GetSimulatorVersion(); } + else if (name == "simulator_hostname") + { + IUrlModule UrlModule = World.RequestModuleInterface(); + return UrlModule.ExternalHostNameForLSL; + } else { return ""; -- cgit v1.1 From 7d26815d0e615b60c708768e8aab19ffd4d118fb Mon Sep 17 00:00:00 2001 From: Magnuz Binder Date: Thu, 14 May 2015 18:28:45 +0200 Subject: Throttle llCastRay V3. Signed-off-by: Michael Cerquoni --- .../Shared/Api/Implementation/LSL_Api.cs | 92 +++++++++++++++++++++- bin/OpenSimDefaults.ini | 16 ++++ 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8359440..d75afb6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.Remoting.Lifetime; @@ -234,6 +235,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected bool m_detectExitsInCastRay = false; protected bool m_filterPartsInCastRay = false; protected bool m_doAttachmentsInCastRay = false; + protected int m_msThrottleInCastRay = 200; + protected int m_msPerRegionInCastRay = 40; + protected int m_msPerAvatarInCastRay = 10; + protected int m_msMinInCastRay = 2; + protected int m_msMaxInCastRay = 40; + protected static List m_castRayCalls = new List(); //An array of HTTP/1.1 headers that are not allowed to be used //as custom headers by llHTTPRequest. @@ -353,6 +360,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); + m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay); + m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay); + m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay); + m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay); + m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay); } IConfig smtpConfig = seConfigSource.Configs["SMTP"]; @@ -14058,10 +14070,61 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options) { - // Initialize m_host.AddScriptLPS(1); - List rayHits = new List(); LSL_List result = new LSL_List(); + + // Prepare throttle data + int calledMs = Environment.TickCount; + Stopwatch stopWatch = new Stopwatch(); + stopWatch.Start(); + UUID regionId = World.RegionInfo.RegionID; + UUID userId = UUID.Zero; + int msAvailable = 0; + // Throttle per owner when attachment or "vehicle" (sat upon) + if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatars().Count > 0) + { + userId = m_host.OwnerID; + msAvailable = m_msPerAvatarInCastRay; + } + // Throttle per parcel when not attachment or vehicle + else + { + LandData land = World.GetLandData(m_host.GetWorldPosition()); + if (land != null) + msAvailable = m_msPerRegionInCastRay * land.Area / 65536; + } + // Clamp for "oversized" parcels on varregions + if (msAvailable > m_msMaxInCastRay) + msAvailable = m_msMaxInCastRay; + + // Check throttle data + int fromCalledMs = calledMs - m_msThrottleInCastRay; + lock (m_castRayCalls) + { + for (int i = m_castRayCalls.Count - 1; i >= 0; i--) + { + // Delete old calls from throttle data + if (m_castRayCalls[i].CalledMs < fromCalledMs) + m_castRayCalls.RemoveAt(i); + // Use current region (in multi-region sims) + else if (m_castRayCalls[i].RegionId == regionId) + { + // Reduce available time with recent calls + if (m_castRayCalls[i].UserId == userId) + msAvailable -= m_castRayCalls[i].UsedMs; + } + } + } + + // Return failure if not enough available time + if (msAvailable < m_msMinInCastRay) + { + result.Add(new LSL_Integer(ScriptBaseClass.RCERR_CAST_TIME_EXCEEDED)); + return result; + } + + // Initialize + List rayHits = new List(); float tol = m_floatToleranceInCastRay; Vector3 pos1Ray = start; Vector3 pos2Ray = end; @@ -14378,6 +14441,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api result.Add(new LSL_Vector(rayHit.Normal)); } result.Add(new LSL_Integer(hitCount)); + + // Add to throttle data + stopWatch.Stop(); + CastRayCall castRayCall = new CastRayCall(); + castRayCall.RegionId = regionId; + castRayCall.UserId = userId; + castRayCall.CalledMs = calledMs; + castRayCall.UsedMs = (int)stopWatch.ElapsedMilliseconds; + lock (m_castRayCalls) + { + m_castRayCalls.Add(castRayCall); + } + + // Return hits return result; } @@ -14412,6 +14489,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// + /// Struct for llCastRay throttle data. + /// + public struct CastRayCall + { + public UUID RegionId; + public UUID UserId; + public int CalledMs; + public int UsedMs; + } + + /// /// Helper to check if a ray intersects a shape bounding box. /// private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax) diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 489ee53..3db59dc 100755 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1535,6 +1535,22 @@ ; Detect attachments in llCastRay V3 if true DoAttachmentsInLlCastRay = false + ; Throttle period length in ms before which all old llCastRay use is discarded in llCastRay V3 + ; The sum of AvailableTimeInMsPerRegionInLlCastRay and all AvailableTimeInMsPerAvatarInLlCastRay should not exceed this + ThrottleTimeInMsInLlCastRay = 200 + + ; Available time in ms for llCastRay per throttle period and 65536 m2 land area in llCastRay V3 + AvailableTimeInMsPerRegionInLlCastRay = 40 + + ; Available time in ms for llCastRay per throttle period and avatar when script in attachment or vehicle in llCastRay V3 + AvailableTimeInMsPerAvatarInLlCastRay = 10 + + ; Required available time in ms left to perform a new llCastRay in llCastRay V3 + RequiredAvailableTimeInMsInLlCastRay = 2 + + ; Maximum available time in ms possible in llCastRay V3, not to get too high values with varregions + MaximumAvailableTimeInMsInLlCastRay = 40 + [DataSnapshot] ; The following set of configs pertains to search. -- cgit v1.1 From fdc383a843c0a0218c194f7f51ef5d8fe774b520 Mon Sep 17 00:00:00 2001 From: Magnuz Binder Date: Tue, 19 May 2015 20:44:19 +0200 Subject: Use own mesh cache in llCastRay V3 after throttling. Signed-off-by: Michael Cerquoni --- .../Shared/Api/Implementation/LSL_Api.cs | 143 +++++++++++++++------ bin/OpenSimDefaults.ini | 8 +- 2 files changed, 110 insertions(+), 41 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d75afb6..e769834 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -223,8 +223,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected float m_primSafetyCoeffY = 2.414214f; protected float m_primSafetyCoeffZ = 1.618034f; protected bool m_useCastRayV3 = false; - protected float m_floatToleranceInCastRay = 0.000001f; - protected float m_floatTolerance2InCastRay = 0.0001f; + protected float m_floatToleranceInCastRay = 0.00001f; + protected float m_floatTolerance2InCastRay = 0.001f; protected DetailLevel m_primLodInCastRay = DetailLevel.Medium; protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium; protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest; @@ -241,6 +241,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected int m_msMinInCastRay = 2; protected int m_msMaxInCastRay = 40; protected static List m_castRayCalls = new List(); + protected bool m_useMeshCacheInCastRay = true; + protected static Dictionary m_cachedMeshes = new Dictionary(); //An array of HTTP/1.1 headers that are not allowed to be used //as custom headers by llHTTPRequest. @@ -365,6 +367,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay); m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay); m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay); + m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay); } IConfig smtpConfig = seConfigSource.Configs["SMTP"]; @@ -14240,50 +14243,85 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api rayTrans.Position1RayProj = pos1RayProj; rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; - // Make an OMV prim to be able to mesh part - Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); - byte[] sculptAsset = null; - if (omvPrim.Sculpt != null) - sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); + // Get detail level depending on type + int lod = 0; + // Mesh detail level + if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) + lod = (int)m_meshLodInCastRay; + // Sculpt detail level + else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) + lod = (int)m_sculptLodInCastRay; + // Shape detail level + else if (!part.Shape.SculptEntry) + lod = (int)m_primLodInCastRay; + + // Try to get cached mesh if configured + ulong meshKey = 0; FacetedMesh mesh = null; - - // When part is mesh, get mesh and check for hits - if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) + if (m_useMeshCacheInCastRay) { - AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); - FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); - meshAsset = null; + meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod)); + lock (m_cachedMeshes) + { + m_cachedMeshes.TryGetValue(meshKey, out mesh); + } } - // When part is sculpt, create mesh and check for hits - // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. - else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) + // Create mesh if no cached mesh + if (mesh == null) { - IJ2KDecoder imgDecoder = World.RequestModuleInterface(); - if (imgDecoder != null) + // Make an OMV prim to be able to mesh part + Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); + byte[] sculptAsset = null; + if (omvPrim.Sculpt != null) + sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); + + // When part is mesh, get mesh + if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) { - Image sculpt = imgDecoder.DecodeToImage(sculptAsset); - if (sculpt != null) + AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); + FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); + meshAsset = null; + } + + // When part is sculpt, create mesh + // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. + else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) + { + IJ2KDecoder imgDecoder = World.RequestModuleInterface(); + if (imgDecoder != null) { - mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); - sculpt.Dispose(); + Image sculpt = imgDecoder.DecodeToImage(sculptAsset); + if (sculpt != null) + { + mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); + sculpt.Dispose(); + } } + } + + // When part is shape, create mesh + else if (omvPrim.Sculpt == null) + { + if ( + omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && + omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && + omvPrim.PrimData.PathSkew == 0.0 && + omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 + ) + rayTrans.ShapeNeedsEnds = false; + mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); } - } - // When part is prim, create mesh and check for hits - else if (omvPrim.Sculpt == null) - { - if ( - omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && - omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && - omvPrim.PrimData.PathSkew == 0.0 && - omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 - ) - rayTrans.ShapeNeedsEnds = false; - mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); + // Cache mesh if configured + if (m_useMeshCacheInCastRay && mesh != null) + { + lock(m_cachedMeshes) + { + m_cachedMeshes.Add(meshKey, mesh); + } + } } - // Check mesh for ray hits AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); mesh = null; @@ -14331,11 +14369,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api rayTrans.Position1RayProj = pos1RayProj; rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; - // Make OMV prim, create and check mesh + // Try to get cached mesh if configured PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere(); - prim.Scale = scalePart; - Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); - FacetedMesh mesh = primMesher.GenerateFacetedMesh(omvPrim, m_meshLodInCastRay); + int lod = (int)m_avatarLodInCastRay; + ulong meshKey = prim.GetMeshKey(Vector3.One, (float)(4 << lod)); + FacetedMesh mesh = null; + if (m_useMeshCacheInCastRay) + { + lock (m_cachedMeshes) + { + m_cachedMeshes.TryGetValue(meshKey, out mesh); + } + } + + // Create mesh if no cached mesh + if (mesh == null) + { + // Make OMV prim and create mesh + prim.Scale = scalePart; + Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); + mesh = primMesher.GenerateFacetedMesh(omvPrim, m_avatarLodInCastRay); + + // Cache mesh if configured + if (m_useMeshCacheInCastRay && mesh != null) + { + lock(m_cachedMeshes) + { + m_cachedMeshes.Add(meshKey, mesh); + } + } + } + + // Check mesh for ray hits AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); mesh = null; } diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 3db59dc..8cde201 100755 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1496,10 +1496,10 @@ UseLlCastRayV3 = false ; Accepted calculation precision error in calculations in llCastRay V3 - FloatToleranceInLlCastRay = 0.000001 + FloatToleranceInLlCastRay = 0.00001 ; Accepted distance difference between duplicate hits in llCastRay V3 - FloatTolerance2InLlCastRay = 0.0001 + FloatTolerance2InLlCastRay = 0.001 ; Detail level when rendering prims in llCastRay V3 ; 0 = Low, 1 = Medium, 2 = High, 3 = Highest, higer level gives better accuracy but slower call @@ -1551,6 +1551,10 @@ ; Maximum available time in ms possible in llCastRay V3, not to get too high values with varregions MaximumAvailableTimeInMsInLlCastRay = 40 + ; Use cached meshes in llCastRay V3 if true + ; Improves performance but uses more memory + UseMeshCacheInLlCastRay = true + [DataSnapshot] ; The following set of configs pertains to search. -- cgit v1.1 From defc9c1d86330b6eecdd5e435bc756e63e83a502 Mon Sep 17 00:00:00 2001 From: Michael Cerquoni Date: Fri, 22 May 2015 01:22:17 -0400 Subject: fix permmission issue on OpenSimDefaults.ini --- bin/OpenSimDefaults.ini | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 bin/OpenSimDefaults.ini diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini old mode 100755 new mode 100644 -- cgit v1.1 From abb3bb60a6ef0a3ed92d3fa54dc47d4d3e560b36 Mon Sep 17 00:00:00 2001 From: Magnuz Binder Date: Sat, 23 May 2015 13:48:37 +0200 Subject: Fix mesh cache race condition in llCastRay V3. Signed-off-by: Michael Cerquoni --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e769834..c5e02a6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -14318,7 +14318,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { lock(m_cachedMeshes) { - m_cachedMeshes.Add(meshKey, mesh); + if (!m_cachedMeshes.ContainsKey(meshKey)) + m_cachedMeshes.Add(meshKey, mesh); } } } @@ -14395,7 +14396,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { lock(m_cachedMeshes) { - m_cachedMeshes.Add(meshKey, mesh); + if (!m_cachedMeshes.ContainsKey(meshKey)) + m_cachedMeshes.Add(meshKey, mesh); } } } -- cgit v1.1