diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 830c6714c8..b0493faaf5 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -1223,12 +1223,16 @@ namespace OpenSim.Groups { if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + // NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information + // to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything. + if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc) + return; + OSDArray AgentData = new OSDArray(1); OSDMap AgentDataMap = new OSDMap(1); AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); AgentData.Add(AgentDataMap); - OSDArray GroupData = new OSDArray(data.Length); OSDArray NewGroupData = new OSDArray(data.Length); @@ -1274,8 +1278,7 @@ namespace OpenSim.Groups if (queue != null) { queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient)); - } - + } } private void SendScenePresenceUpdate(UUID AgentID, string Title) @@ -1337,6 +1340,7 @@ namespace OpenSim.Groups GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, dataForAgentID); SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray); + //remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray); if (remoteClient.AgentId == dataForAgentID) remoteClient.RefreshGroupMembership(); diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs index c33168ce26..4642b2adaf 100644 --- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs +++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs @@ -404,7 +404,7 @@ namespace OpenSim.Groups url = m_UserManagement.GetUserServerURL(uid, "GroupsServerURI"); if (url == string.Empty) { - reason = "You don't have have an accessible groups server in your home world. You membership to this group in only within this grid."; + reason = "You don't have an accessible groups server in your home world. You membership to this group in only within this grid."; return true; } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 4272375c5e..725bf06734 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -229,7 +229,12 @@ namespace OpenSim.Region.ClientStack.Linden queue.Enqueue(ev); } else - m_log.WarnFormat("[EVENTQUEUE]: (Enqueue) No queue found for agent {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName); + { + OSDMap evMap = (OSDMap)ev; + m_log.WarnFormat( + "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} when placing message {1} in region {2}", + avatarID, evMap["message"], m_scene.Name); + } } catch (NullReferenceException e) { @@ -365,14 +370,14 @@ namespace OpenSim.Region.ClientStack.Linden OSDMap ev = (OSDMap)element; m_log.DebugFormat( "Eq OUT {0,-30} to {1,-20} {2,-20}", - ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.RegionInfo.RegionName); + ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.Name); } } public Hashtable GetEvents(UUID requestID, UUID pAgentId) { if (DebugLevel >= 2) - m_log.WarnFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName); + m_log.WarnFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.Name); Queue queue = GetQueue(pAgentId); if (queue == null) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 7c8c189efe..35045b5008 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -799,7 +799,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests } [Test] - public void TestSameSimulatorNeighbouringRegionsTeleport() + public void TestSameSimulatorNeighbouringRegionsTeleportV1() { TestHelpers.InMethod(); // TestHelpers.EnableLogging(); @@ -904,5 +904,116 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Check events Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } + + [Test] + public void TestSameSimulatorNeighbouringRegionsTeleportV2() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + BaseHttpServer httpServer = new BaseHttpServer(99999); + MainServer.AddHttpServer(httpServer); + MainServer.Instance = httpServer; + + AttachmentsModule attModA = new AttachmentsModule(); + AttachmentsModule attModB = new AttachmentsModule(); + EntityTransferModule etmA = new EntityTransferModule(); + EntityTransferModule etmB = new EntityTransferModule(); + LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); + + IConfigSource config = new IniConfigSource(); + IConfig modulesConfig = config.AddConfig("Modules"); + modulesConfig.Set("EntityTransferModule", etmA.Name); + modulesConfig.Set("SimulationServices", lscm.Name); + IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); + + modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule"); + + SceneHelpers sh = new SceneHelpers(); + TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); + TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000); + + SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); + SceneHelpers.SetupSceneModules( + sceneA, config, new CapabilitiesModule(), etmA, attModA, new BasicInventoryAccessModule()); + SceneHelpers.SetupSceneModules( + sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); + + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); + + AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); + TestClient tc = new TestClient(acd, sceneA); + List destinationTestClients = new List(); + EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); + + ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd); + beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32); + + Assert.That(destinationTestClients.Count, Is.EqualTo(1)); + Assert.That(destinationTestClients[0], Is.Not.Null); + + InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20); + + sceneA.AttachmentsModule.RezSingleAttachmentFromInventory( + beforeTeleportSp, attItem.ID, (uint)AttachmentPoint.Chest); + + Vector3 teleportPosition = new Vector3(10, 11, 12); + Vector3 teleportLookAt = new Vector3(20, 21, 22); + + // Here, we need to make clientA's receipt of SendRegionTeleport trigger clientB's CompleteMovement(). This + // is to operate the teleport V2 mechanism where the EntityTransferModule will first request the client to + // CompleteMovement to the region and then call UpdateAgent to the destination region to confirm the receipt + // Both these operations will occur on different threads and will wait for each other. + // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1 + // test protocol, where we are trying to avoid unpredictable async operations in regression tests. + ((TestClient)beforeTeleportSp.ControllingClient).OnTestClientSendRegionTeleport + += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) + => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null); + + m_numberOfAttachEventsFired = 0; + sceneA.RequestTeleportLocation( + beforeTeleportSp.ControllingClient, + sceneB.RegionInfo.RegionHandle, + teleportPosition, + teleportLookAt, + (uint)TeleportFlags.ViaLocation); + + // Check attachments have made it into sceneB + ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID); + + // This is appearance data, as opposed to actually rezzed attachments + List sceneBAttachments = afterTeleportSceneBSp.Appearance.GetAttachments(); + Assert.That(sceneBAttachments.Count, Is.EqualTo(1)); + Assert.That(sceneBAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest)); + Assert.That(sceneBAttachments[0].ItemID, Is.EqualTo(attItem.ID)); + Assert.That(sceneBAttachments[0].AssetID, Is.EqualTo(attItem.AssetID)); + Assert.That(afterTeleportSceneBSp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); + + // This is the actual attachment + List actualSceneBAttachments = afterTeleportSceneBSp.GetAttachments(); + Assert.That(actualSceneBAttachments.Count, Is.EqualTo(1)); + SceneObjectGroup actualSceneBAtt = actualSceneBAttachments[0]; + Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name)); + Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest)); + + Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1)); + + // Check attachments have been removed from sceneA + ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID); + + // Since this is appearance data, it is still present on the child avatar! + List sceneAAttachments = afterTeleportSceneASp.Appearance.GetAttachments(); + Assert.That(sceneAAttachments.Count, Is.EqualTo(1)); + Assert.That(afterTeleportSceneASp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); + + // This is the actual attachment, which should no longer exist + List actualSceneAAttachments = afterTeleportSceneASp.GetAttachments(); + Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); + + Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); + + // Check events + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); + } } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index e0f061b0e1..8a734e1d2e 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1212,7 +1212,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); AgentData.Add(AgentDataMap); - OSDArray GroupData = new OSDArray(data.Length); OSDArray NewGroupData = new OSDArray(data.Length); diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index b0a29c048e..78fe09625a 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -377,7 +377,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove", agentID, av.Name); */ - scene.RemoveClient(agentID, false); + + scene.IncomingCloseAgent(agentID, false); +// scene.RemoveClient(agentID, false); m_avatars.Remove(agentID); // m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}", agentID, av.Name); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index 0f11c4a158..5f232a4b99 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -311,21 +311,28 @@ public class BSActorAvatarMove : BSActor // Don't care about collisions with the terrain if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID) { - OMV.Vector3 touchPosition = kvp.Value.Position; - m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", - m_controllingPrim.LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); - if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) + BSPhysObject collisionObject; + if (m_physicsScene.PhysObjects.TryGetValue(kvp.Key, out collisionObject)) { - // This contact is within the 'near the feet' range. - // The normal should be our contact point to the object so it is pointing away - // thus the difference between our facing orientation and the normal should be small. - OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation; - OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal); - float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); - if (diff < BSParam.AvatarStepApproachFactor) + if (!collisionObject.IsVolumeDetect) { - if (highestTouchPosition.Z < touchPosition.Z) - highestTouchPosition = touchPosition; + OMV.Vector3 touchPosition = kvp.Value.Position; + m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", + m_controllingPrim.LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); + if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) + { + // This contact is within the 'near the feet' range. + // The normal should be our contact point to the object so it is pointing away + // thus the difference between our facing orientation and the normal should be small. + OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation; + OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal); + float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); + if (diff < BSParam.AvatarStepApproachFactor) + { + if (highestTouchPosition.Z < touchPosition.Z) + highestTouchPosition = touchPosition; + } + } } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 9af3dcea48..d584782e74 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -404,6 +404,7 @@ public sealed class BSCharacter : BSPhysObject // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more public override void SetVolumeDetect(int param) { return; } + public override bool IsVolumeDetect { get { return false; } } public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 07045919e8..27caf62873 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -175,6 +175,7 @@ public abstract class BSPhysObject : PhysicsActor public abstract bool IsSolid { get; } public abstract bool IsStatic { get; } public abstract bool IsSelected { get; } + public abstract bool IsVolumeDetect { get; } // Materialness public MaterialAttributes.Material Material { get; private set; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index a0b6abc01f..6b5dea39ff 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -617,6 +617,10 @@ public class BSPrim : BSPhysObject } return; } + public override bool IsVolumeDetect + { + get { return _isVolumeDetect; } + } public override void SetMaterial(int material) { base.SetMaterial(material); diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 3646c989fd..2fb073decf 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -533,7 +533,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_log.Warn( string.Format( "[SCRIPT INSTANCE]: Could not delete script state {0} for script {1} (id {2}) in part {3} (id {4}) in object {5} in {6}. Exception ", - ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name), + savedState, ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name), e); } } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index df8cf2752e..e8520f211b 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -61,8 +61,13 @@ namespace OpenSim.Tests.Common.Mock // Test client specific events - for use by tests to implement some IClientAPI behaviour. public event Action OnReceivedMoveAgentIntoRegion; public event Action OnTestClientInformClientOfNeighbour; + public event TestClientOnSendRegionTeleportDelegate OnTestClientSendRegionTeleport; public event Action OnReceivedInstantMessage; + public delegate void TestClientOnSendRegionTeleportDelegate( + ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, + uint locationID, uint flags, string capsURL); + // disable warning: public events, part of the public API #pragma warning disable 67 @@ -475,7 +480,8 @@ namespace OpenSim.Tests.Common.Mock public void CompleteMovement() { - OnCompleteMovementToRegion(this, true); + if (OnCompleteMovementToRegion != null) + OnCompleteMovementToRegion(this, true); } /// @@ -615,21 +621,25 @@ namespace OpenSim.Tests.Common.Mock OnTestClientInformClientOfNeighbour(neighbourHandle, neighbourExternalEndPoint); } - public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, - uint locationID, uint flags, string capsURL) + public virtual void SendRegionTeleport( + ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, + uint locationID, uint flags, string capsURL) { - m_log.DebugFormat("[TEST CLIENT]: Received SendRegionTeleport"); + m_log.DebugFormat( + "[TEST CLIENT]: Received SendRegionTeleport for {0} {1} on {2}", m_firstName, m_lastName, m_scene.Name); CapsSeedUrl = capsURL; - // We don't do this here so that the source region can complete processing first in a single-threaded - // regression test scenario. The test itself will have to call CompleteTeleportClientSide() after a teleport - // CompleteTeleportClientSide(); + if (OnTestClientSendRegionTeleport != null) + OnTestClientSendRegionTeleport( + regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL); } public virtual void SendTeleportFailed(string reason) { - m_log.DebugFormat("[TEST CLIENT]: Teleport failed with reason {0}", reason); + m_log.DebugFormat( + "[TEST CLIENT]: Teleport failed for {0} {1} on {2} with reason {3}", + m_firstName, m_lastName, m_scene.Name, reason); } public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt, diff --git a/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs new file mode 100644 index 0000000000..9cf8a54594 --- /dev/null +++ b/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs @@ -0,0 +1,43 @@ +/* + * 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 OpenMetaverse; +using System; +using System.Collections.Generic; +using System.Linq; +using pCampBot.Interfaces; + +namespace pCampBot +{ + /// + /// Do nothing + /// + public class NoneBehaviour : AbstractBehaviour + { + public NoneBehaviour() { Name = "None"; } + } +} \ No newline at end of file diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs index d615b3fb8a..74bd36a9a9 100644 --- a/OpenSim/Tools/pCampBot/BotManager.cs +++ b/OpenSim/Tools/pCampBot/BotManager.cs @@ -177,18 +177,21 @@ namespace pCampBot // We must give each bot its own list of instantiated behaviours since they store state. List behaviours = new List(); - // Hard-coded for now + // Hard-coded for now + if (behaviourSwitches.Contains("c")) + behaviours.Add(new CrossBehaviour()); + + if (behaviourSwitches.Contains("g")) + behaviours.Add(new GrabbingBehaviour()); + + if (behaviourSwitches.Contains("n")) + behaviours.Add(new NoneBehaviour()); + if (behaviourSwitches.Contains("p")) behaviours.Add(new PhysicsBehaviour()); - if (behaviourSwitches.Contains("g")) - behaviours.Add(new GrabbingBehaviour()); - if (behaviourSwitches.Contains("t")) behaviours.Add(new TeleportBehaviour()); - - if (behaviourSwitches.Contains("c")) - behaviours.Add(new CrossBehaviour()); StartBot(this, behaviours, firstName, lastName, password, loginUri); } @@ -327,17 +330,30 @@ namespace pCampBot string outputFormat = "{0,-30} {1, -30} {2,-14}"; MainConsole.Instance.OutputFormat(outputFormat, "Name", "Region", "Status"); + Dictionary totals = new Dictionary(); + foreach (object o in Enum.GetValues(typeof(ConnectionState))) + totals[(ConnectionState)o] = 0; + lock (m_lBot) { foreach (Bot pb in m_lBot) { Simulator currentSim = pb.Client.Network.CurrentSim; + totals[pb.ConnectionState]++; MainConsole.Instance.OutputFormat( outputFormat, pb.Name, currentSim != null ? currentSim.Name : "(none)", pb.ConnectionState); } } + + ConsoleDisplayList cdl = new ConsoleDisplayList(); + + foreach (KeyValuePair kvp in totals) + cdl.AddRow(kvp.Key, kvp.Value); + + + MainConsole.Instance.OutputFormat("\n{0}", cdl.ToString()); } /* diff --git a/OpenSim/Tools/pCampBot/pCampBot.cs b/OpenSim/Tools/pCampBot/pCampBot.cs index 9e82577be5..2707a49f7d 100644 --- a/OpenSim/Tools/pCampBot/pCampBot.cs +++ b/OpenSim/Tools/pCampBot/pCampBot.cs @@ -123,9 +123,10 @@ namespace pCampBot " -password password for the bots\n" + " -b, behaviours behaviours for bots. Comma separated, e.g. p,g. Default is p\n" + " current options are:\n" + - " p (physics)\n" + - " g (grab)\n" + - " t (teleport)\n" + + " p (physics - bots constantly move and jump around)\n" + + " g (grab - bots randomly click prims whether set clickable or not)\n" + + " n (none - bots do nothing)\n" + + " t (teleport - bots regularly teleport between regions on the grid)\n" + // " c (cross)" + " -wear set appearance folder to load from (default: no)\n" + " -h, -help show this message");