From 134f86e8d5c414409631b25b8c6f0ee45fbd8631 Mon Sep 17 00:00:00 2001
From: David Walter Seikel
Date: Thu, 3 Nov 2016 21:44:39 +1000
Subject: Initial update to OpenSim 0.8.2.1 source code.
---
OpenSim/Tools/pCampBot/Bot.cs | 348 +++++++++++++++++++++++++++++++++---------
1 file changed, 274 insertions(+), 74 deletions(-)
(limited to 'OpenSim/Tools/pCampBot/Bot.cs')
diff --git a/OpenSim/Tools/pCampBot/Bot.cs b/OpenSim/Tools/pCampBot/Bot.cs
index daaa3c0..4f28733 100644
--- a/OpenSim/Tools/pCampBot/Bot.cs
+++ b/OpenSim/Tools/pCampBot/Bot.cs
@@ -35,11 +35,13 @@ using System.Timers;
using log4net;
using OpenMetaverse;
using OpenMetaverse.Assets;
+using OpenMetaverse.Packets;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using pCampBot.Interfaces;
using Timer = System.Timers.Timer;
+using PermissionMask = OpenSim.Framework.PermissionMask;
namespace pCampBot
{
@@ -55,25 +57,47 @@ namespace pCampBot
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ public int PacketDebugLevel
+ {
+ get { return m_packetDebugLevel; }
+ set
+ {
+ if (value == m_packetDebugLevel)
+ return;
+
+ m_packetDebugLevel = value;
+
+ if (Client != null)
+ {
+ if (m_packetDebugLevel <= 0)
+ Client.Network.UnregisterCallback(PacketType.Default, PacketReceivedDebugHandler);
+ else
+ Client.Network.RegisterCallback(PacketType.Default, PacketReceivedDebugHandler, false);
+ }
+ }
+ }
+ private int m_packetDebugLevel;
+
public delegate void AnEvent(Bot callbot, EventType someevent); // event delegate for bot events
///
- /// Bot manager.
+ /// Controls whether bots request textures for the object information they receive
///
- public BotManager Manager { get; private set; }
+ public bool RequestObjectTextures { get; set; }
///
- /// Bot config, passed from BotManager.
+ /// Bot manager.
///
- private IConfig startupConfig;
+ public BotManager Manager { get; private set; }
///
/// Behaviours implemented by this bot.
///
///
- /// Lock this list before manipulating it.
+ /// Indexed by abbreviated name. There can only be one instance of a particular behaviour.
+ /// Lock this structure before manipulating it.
///
- public List Behaviours { get; private set; }
+ public Dictionary Behaviours { get; private set; }
///
/// Objects that the bot has discovered.
@@ -96,11 +120,35 @@ namespace pCampBot
///
public ConnectionState ConnectionState { get; private set; }
+ public List Simulators
+ {
+ get
+ {
+ lock (Client.Network.Simulators)
+ return new List(Client.Network.Simulators);
+ }
+ }
+
+ ///
+ /// The number of connections that this bot has to different simulators.
+ ///
+ /// Includes both root and child connections.
+ public int SimulatorsCount
+ {
+ get
+ {
+ lock (Client.Network.Simulators)
+ return Client.Network.Simulators.Count;
+ }
+ }
+
public string FirstName { get; private set; }
public string LastName { get; private set; }
public string Name { get; private set; }
public string Password { get; private set; }
public string LoginUri { get; private set; }
+ public string StartLocation { get; private set; }
+
public string saveDir;
public string wear;
@@ -136,94 +184,180 @@ namespace pCampBot
///
public Bot(
BotManager bm, List behaviours,
- string firstName, string lastName, string password, string loginUri)
+ string firstName, string lastName, string password, string startLocation, string loginUri)
{
ConnectionState = ConnectionState.Disconnected;
- behaviours.ForEach(b => b.Initialize(this));
-
- Client = new GridClient();
-
- Random = new Random(Environment.TickCount);// We do stuff randomly here
+ Random = new Random(bm.Rng.Next());
FirstName = firstName;
LastName = lastName;
Name = string.Format("{0} {1}", FirstName, LastName);
Password = password;
LoginUri = loginUri;
+ StartLocation = startLocation;
Manager = bm;
- startupConfig = bm.Config;
- readconfig();
- Behaviours = behaviours;
+ Behaviours = new Dictionary();
+ foreach (IBehaviour behaviour in behaviours)
+ AddBehaviour(behaviour);
+
+ // Only calling for use as a template.
+ CreateLibOmvClient();
+ }
+
+ public bool TryGetBehaviour(string abbreviatedName, out IBehaviour behaviour)
+ {
+ lock (Behaviours)
+ return Behaviours.TryGetValue(abbreviatedName, out behaviour);
+ }
+
+ public bool AddBehaviour(IBehaviour behaviour)
+ {
+ Dictionary updatedBehaviours = new Dictionary(Behaviours);
+
+ if (!updatedBehaviours.ContainsKey(behaviour.AbbreviatedName))
+ {
+ behaviour.Initialize(this);
+ updatedBehaviours.Add(behaviour.AbbreviatedName, behaviour);
+ Behaviours = updatedBehaviours;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool RemoveBehaviour(string abbreviatedName)
+ {
+ if (Behaviours.Count <= 0)
+ return false;
+
+ Dictionary updatedBehaviours = new Dictionary(Behaviours);
+ IBehaviour behaviour;
+
+ if (!updatedBehaviours.TryGetValue(abbreviatedName, out behaviour))
+ return false;
+
+ updatedBehaviours.Remove(abbreviatedName);
+ Behaviours = updatedBehaviours;
+
+ behaviour.Close();
+
+ return true;
+ }
+
+ private void CreateLibOmvClient()
+ {
+ GridClient newClient = new GridClient();
+
+ if (Client != null)
+ {
+ // Remove any registered debug handlers
+ Client.Network.UnregisterCallback(PacketType.Default, PacketReceivedDebugHandler);
+
+ newClient.Settings.LOGIN_SERVER = Client.Settings.LOGIN_SERVER;
+ newClient.Settings.ALWAYS_DECODE_OBJECTS = Client.Settings.ALWAYS_DECODE_OBJECTS;
+ newClient.Settings.AVATAR_TRACKING = Client.Settings.AVATAR_TRACKING;
+ newClient.Settings.OBJECT_TRACKING = Client.Settings.OBJECT_TRACKING;
+ newClient.Settings.SEND_AGENT_THROTTLE = Client.Settings.SEND_AGENT_THROTTLE;
+ newClient.Settings.SEND_AGENT_UPDATES = Client.Settings.SEND_AGENT_UPDATES;
+ newClient.Settings.SEND_PINGS = Client.Settings.SEND_PINGS;
+ newClient.Settings.STORE_LAND_PATCHES = Client.Settings.STORE_LAND_PATCHES;
+ newClient.Settings.USE_ASSET_CACHE = Client.Settings.USE_ASSET_CACHE;
+ newClient.Settings.MULTIPLE_SIMS = Client.Settings.MULTIPLE_SIMS;
+ newClient.Throttle.Asset = Client.Throttle.Asset;
+ newClient.Throttle.Land = Client.Throttle.Land;
+ newClient.Throttle.Task = Client.Throttle.Task;
+ newClient.Throttle.Texture = Client.Throttle.Texture;
+ newClient.Throttle.Wind = Client.Throttle.Wind;
+ newClient.Throttle.Total = Client.Throttle.Total;
+ }
+ else
+ {
+ newClient.Settings.LOGIN_SERVER = LoginUri;
+ newClient.Settings.ALWAYS_DECODE_OBJECTS = false;
+ newClient.Settings.AVATAR_TRACKING = false;
+ newClient.Settings.OBJECT_TRACKING = false;
+ newClient.Settings.SEND_AGENT_THROTTLE = true;
+ newClient.Settings.SEND_PINGS = true;
+ newClient.Settings.STORE_LAND_PATCHES = false;
+ newClient.Settings.USE_ASSET_CACHE = false;
+ newClient.Settings.MULTIPLE_SIMS = true;
+ newClient.Throttle.Asset = 100000;
+ newClient.Throttle.Land = 100000;
+ newClient.Throttle.Task = 100000;
+ newClient.Throttle.Texture = 100000;
+ newClient.Throttle.Wind = 100000;
+ newClient.Throttle.Total = 400000;
+ }
+
+ newClient.Network.LoginProgress += Network_LoginProgress;
+ newClient.Network.SimConnected += Network_SimConnected;
+ newClient.Network.SimDisconnected += Network_SimDisconnected;
+ newClient.Network.Disconnected += Network_OnDisconnected;
+ newClient.Objects.ObjectUpdate += Objects_NewPrim;
+
+ if (m_packetDebugLevel > 0)
+ newClient.Network.RegisterCallback(PacketType.Default, PacketReceivedDebugHandler);
+
+ Client = newClient;
}
//We do our actions here. This is where one would
//add additional steps and/or things the bot should do
private void Action()
{
- while (true)
- lock (Behaviours)
- Behaviours.ForEach(
- b =>
- {
- Thread.Sleep(Random.Next(3000, 10000));
-
- // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType());
- b.Action();
- }
- );
- }
+ while (ConnectionState == ConnectionState.Connected)
+ {
+ foreach (IBehaviour behaviour in Behaviours.Values)
+ {
+// Thread.Sleep(Random.Next(3000, 10000));
+
+ // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType());
+ behaviour.Action();
+ }
+ }
- ///
- /// Read the Nini config and initialize
- ///
- public void readconfig()
- {
- wear = startupConfig.GetString("wear", "no");
+ foreach (IBehaviour b in Behaviours.Values)
+ b.Close();
}
///
/// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes.
///
- public void shutdown()
+ public void Disconnect()
{
ConnectionState = ConnectionState.Disconnecting;
-
- if (m_actionThread != null)
- m_actionThread.Abort();
+
+ foreach (IBehaviour behaviour in Behaviours.Values)
+ behaviour.Close();
Client.Network.Logout();
}
+ public void Connect()
+ {
+ Thread connectThread = new Thread(ConnectInternal);
+ connectThread.Name = Name;
+ connectThread.IsBackground = true;
+
+ connectThread.Start();
+ }
+
///
/// This is the bot startup loop.
///
- public void startup()
+ private void ConnectInternal()
{
- Client.Settings.LOGIN_SERVER = LoginUri;
- Client.Settings.ALWAYS_DECODE_OBJECTS = false;
- Client.Settings.AVATAR_TRACKING = false;
- Client.Settings.OBJECT_TRACKING = false;
- Client.Settings.SEND_AGENT_THROTTLE = true;
- Client.Settings.SEND_PINGS = true;
- Client.Settings.STORE_LAND_PATCHES = false;
- Client.Settings.USE_ASSET_CACHE = false;
- Client.Settings.MULTIPLE_SIMS = true;
- Client.Throttle.Asset = 100000;
- Client.Throttle.Land = 100000;
- Client.Throttle.Task = 100000;
- Client.Throttle.Texture = 100000;
- Client.Throttle.Wind = 100000;
- Client.Throttle.Total = 400000;
- Client.Network.LoginProgress += this.Network_LoginProgress;
- Client.Network.SimConnected += this.Network_SimConnected;
- Client.Network.Disconnected += this.Network_OnDisconnected;
- Client.Objects.ObjectUpdate += Objects_NewPrim;
-
ConnectionState = ConnectionState.Connecting;
- if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", "Your name"))
+ // Current create a new client on each connect. libomv doesn't seem to process new sim
+ // information (e.g. EstablishAgentCommunication events) if connecting after a disceonnect with the same
+ // client
+ CreateLibOmvClient();
+
+ if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", StartLocation, "pCampBot"))
{
ConnectionState = ConnectionState.Connected;
@@ -234,7 +368,6 @@ namespace pCampBot
// OnConnected(this, EventType.CONNECTED);
if (wear == "save")
{
- Client.Appearance.SetPreviousAppearance();
SaveDefaultAppearance();
}
else if (wear != "no")
@@ -267,6 +400,30 @@ namespace pCampBot
}
}
+ ///
+ /// Sit this bot on the ground.
+ ///
+ public void SitOnGround()
+ {
+ if (ConnectionState == ConnectionState.Connected)
+ Client.Self.SitOnGround();
+ }
+
+ ///
+ /// Stand this bot
+ ///
+ public void Stand()
+ {
+ if (ConnectionState == ConnectionState.Connected)
+ {
+ // Unlike sit on ground, here libomv checks whether we have SEND_AGENT_UPDATES enabled.
+ bool prevUpdatesSetting = Client.Settings.SEND_AGENT_UPDATES;
+ Client.Settings.SEND_AGENT_UPDATES = true;
+ Client.Self.Stand();
+ Client.Settings.SEND_AGENT_UPDATES = prevUpdatesSetting;
+ }
+ }
+
public void SaveDefaultAppearance()
{
saveDir = "MyAppearance/" + FirstName + "_" + LastName;
@@ -362,7 +519,7 @@ namespace pCampBot
asset.Encode();
transid = Client.Assets.RequestUpload(asset,true);
Client.Inventory.RequestCreateItem(clothfolder.UUID, "MyClothing" + i.ToString(), "MyClothing", AssetType.Clothing,
- transid, InventoryType.Wearable, asset.WearableType, PermissionMask.All, delegate(bool success, InventoryItem item)
+ transid, InventoryType.Wearable, asset.WearableType, (OpenMetaverse.PermissionMask)PermissionMask.All, delegate(bool success, InventoryItem item)
{
if (success)
{
@@ -386,7 +543,7 @@ namespace pCampBot
asset.Encode();
transid = Client.Assets.RequestUpload(asset,true);
Client.Inventory.RequestCreateItem(clothfolder.UUID, "MyBodyPart" + i.ToString(), "MyBodyPart", AssetType.Bodypart,
- transid, InventoryType.Wearable, asset.WearableType, PermissionMask.All, delegate(bool success, InventoryItem item)
+ transid, InventoryType.Wearable, asset.WearableType, (OpenMetaverse.PermissionMask)PermissionMask.All, delegate(bool success, InventoryItem item)
{
if (success)
{
@@ -450,7 +607,13 @@ namespace pCampBot
public void Network_SimConnected(object sender, SimConnectedEventArgs args)
{
m_log.DebugFormat(
- "[BOT]: Bot {0} connected to {1} at {2}", Name, args.Simulator.Name, args.Simulator.IPEndPoint);
+ "[BOT]: Bot {0} connected to region {1} at {2}", Name, args.Simulator.Name, args.Simulator.IPEndPoint);
+ }
+
+ public void Network_SimDisconnected(object sender, SimDisconnectedEventArgs args)
+ {
+ m_log.DebugFormat(
+ "[BOT]: Bot {0} disconnected from region {1} at {2}", Name, args.Simulator.Name, args.Simulator.IPEndPoint);
}
public void Network_OnDisconnected(object sender, DisconnectedEventArgs args)
@@ -458,7 +621,7 @@ namespace pCampBot
ConnectionState = ConnectionState.Disconnected;
m_log.DebugFormat(
- "[BOT]: Bot {0} disconnected reason {1}, message {2}", Name, args.Reason, args.Message);
+ "[BOT]: Bot {0} disconnected from grid, reason {1}, message {2}", Name, args.Reason, args.Message);
// m_log.ErrorFormat("Fired Network_OnDisconnected");
@@ -467,6 +630,8 @@ namespace pCampBot
// || args.Reason == NetworkManager.DisconnectType.NetworkTimeout)
// && OnDisconnected != null)
+
+
if (
(args.Reason == NetworkManager.DisconnectType.ClientInitiated
|| args.Reason == NetworkManager.DisconnectType.ServerInitiated
@@ -480,8 +645,8 @@ namespace pCampBot
public void Objects_NewPrim(object sender, PrimEventArgs args)
{
-// if (Name.EndsWith("4"))
-// throw new Exception("Aaargh");
+ if (!RequestObjectTextures)
+ return;
Primitive prim = args.Prim;
@@ -494,7 +659,7 @@ namespace pCampBot
{
if (prim.Textures.DefaultTexture.TextureID != UUID.Zero)
{
- GetTexture(prim.Textures.DefaultTexture.TextureID);
+ GetTextureOrMesh(prim.Textures.DefaultTexture.TextureID, true);
}
for (int i = 0; i < prim.Textures.FaceTextures.Length; i++)
@@ -506,32 +671,56 @@ namespace pCampBot
UUID textureID = prim.Textures.FaceTextures[i].TextureID;
if (textureID != UUID.Zero)
- GetTexture(textureID);
+ GetTextureOrMesh(textureID, true);
}
}
}
if (prim.Sculpt != null && prim.Sculpt.SculptTexture != UUID.Zero)
- GetTexture(prim.Sculpt.SculptTexture);
+ {
+ bool mesh = (prim.Sculpt.Type == SculptType.Mesh);
+ GetTextureOrMesh(prim.Sculpt.SculptTexture, !mesh);
+ }
}
}
- private void GetTexture(UUID textureID)
+ private void GetTextureOrMesh(UUID assetID, bool texture)
{
lock (Manager.AssetsReceived)
{
// Don't request assets more than once.
- if (Manager.AssetsReceived.ContainsKey(textureID))
+ if (Manager.AssetsReceived.ContainsKey(assetID))
return;
- Manager.AssetsReceived[textureID] = false;
- Client.Assets.RequestImage(textureID, ImageType.Normal, Asset_TextureCallback_Texture);
+ Manager.AssetsReceived[assetID] = false;
+ }
+
+ try
+ {
+ if (texture)
+ Client.Assets.RequestImage(assetID, ImageType.Normal, Asset_TextureCallback_Texture);
+ else
+ Client.Assets.RequestMesh(assetID, Asset_MeshCallback);
+ }
+ catch (Exception e)
+ {
+ m_log.Warn(string.Format("Error requesting {0} {1}", texture ? "texture" : "mesh", assetID), e);
}
}
public void Asset_TextureCallback_Texture(TextureRequestState state, AssetTexture assetTexture)
{
- //TODO: Implement texture saving and applying
+ if (state == TextureRequestState.Finished)
+ {
+ lock (Manager.AssetsReceived)
+ Manager.AssetsReceived[assetTexture.AssetID] = true;
+ }
+ }
+
+ private void Asset_MeshCallback(bool success, AssetMesh assetMesh)
+ {
+ lock (Manager.AssetsReceived)
+ Manager.AssetsReceived[assetMesh.AssetID] = success;
}
public void Asset_ReceivedCallback(AssetDownload transfer, Asset asset)
@@ -544,5 +733,16 @@ namespace pCampBot
// SaveAsset((AssetWearable) asset);
// }
}
+
+ private void PacketReceivedDebugHandler(object o, PacketReceivedEventArgs args)
+ {
+ Packet p = args.Packet;
+ Header h = p.Header;
+ Simulator s = args.Simulator;
+
+ m_log.DebugFormat(
+ "[BOT]: Bot {0} received from {1} packet {2} #{3}, rel {4}, res {5}",
+ Name, s.Name, p.Type, h.Sequence, h.Reliable, h.Resent);
+ }
}
}
--
cgit v1.1