diff --git a/OpenSim/Tools/pCampBot/Bot.cs b/OpenSim/Tools/pCampBot/Bot.cs
index d418288434..60375162cb 100644
--- a/OpenSim/Tools/pCampBot/Bot.cs
+++ b/OpenSim/Tools/pCampBot/Bot.cs
@@ -72,9 +72,10 @@ namespace pCampBot
/// 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.
@@ -165,8 +166,6 @@ namespace pCampBot
{
ConnectionState = ConnectionState.Disconnected;
- behaviours.ForEach(b => b.Initialize(this));
-
Random = new Random(Environment.TickCount);// We do stuff randomly here
FirstName = firstName;
LastName = lastName;
@@ -176,12 +175,31 @@ namespace pCampBot
StartLocation = startLocation;
Manager = bm;
- Behaviours = behaviours;
+
+ Behaviours = new Dictionary();
+ foreach (IBehaviour behaviour in behaviours)
+ AddBehaviour(behaviour);
// Only calling for use as a template.
CreateLibOmvClient();
}
+ public bool AddBehaviour(IBehaviour behaviour)
+ {
+ lock (Behaviours)
+ {
+ if (!Behaviours.ContainsKey(behaviour.AbbreviatedName))
+ {
+ behaviour.Initialize(this);
+ Behaviours.Add(behaviour.AbbreviatedName, behaviour);
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private void CreateLibOmvClient()
{
GridClient newClient = new GridClient();
@@ -237,16 +255,21 @@ namespace pCampBot
private void Action()
{
while (ConnectionState != ConnectionState.Disconnecting)
+ {
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();
- }
- );
+ {
+ 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();
+ }
+ }
+
+ // XXX: This is a really shitty way of yielding so that behaviours can be added/removed
+ Thread.Sleep(100);
+ }
}
///
diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs
index 3e446af417..51c5ff4c93 100644
--- a/OpenSim/Tools/pCampBot/BotManager.cs
+++ b/OpenSim/Tools/pCampBot/BotManager.cs
@@ -140,7 +140,7 @@ namespace pCampBot
///
/// Behaviour switches for bots.
///
- private HashSet m_behaviourSwitches = new HashSet();
+ private HashSet m_defaultBehaviourSwitches = new HashSet();
///
/// Constructor Creates MainConsole.Instance to take commands and provide the place to write data
@@ -194,6 +194,18 @@ namespace pCampBot
+ "If no is given, then all currently connected bots are disconnected.",
HandleDisconnect);
+ m_console.Commands.AddCommand(
+ "bot", false, "add behaviour", "add behaviour ",
+ "Add a behaviour to a bot",
+ "Can be performed on connected or disconnected bots.",
+ HandleAddBehaviour);
+
+// m_console.Commands.AddCommand(
+// "bot", false, "remove behaviour", "remove behaviour ",
+// "Remove a behaviour from a bot",
+// "Can be performed on connected or disconnected bots.",
+// HandleRemoveBehaviour);
+
m_console.Commands.AddCommand(
"bot", false, "sit", "sit", "Sit all bots on the ground.",
HandleSit);
@@ -235,7 +247,7 @@ namespace pCampBot
m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last"));
Array.ForEach(
- startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_behaviourSwitches.Add(b));
+ startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_defaultBehaviourSwitches.Add(b));
for (int i = 0; i < botcount; i++)
{
@@ -243,30 +255,52 @@ namespace pCampBot
{
string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber);
- // We must give each bot its own list of instantiated behaviours since they store state.
- List behaviours = new List();
-
- // Hard-coded for now
- if (m_behaviourSwitches.Contains("c"))
- behaviours.Add(new CrossBehaviour());
-
- if (m_behaviourSwitches.Contains("g"))
- behaviours.Add(new GrabbingBehaviour());
-
- if (m_behaviourSwitches.Contains("n"))
- behaviours.Add(new NoneBehaviour());
-
- if (m_behaviourSwitches.Contains("p"))
- behaviours.Add(new PhysicsBehaviour());
-
- if (m_behaviourSwitches.Contains("t"))
- behaviours.Add(new TeleportBehaviour());
-
- CreateBot(this, behaviours, m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
+ CreateBot(
+ this,
+ CreateBehavioursFromAbbreviatedNames(m_defaultBehaviourSwitches),
+ m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
}
}
}
+ private List CreateBehavioursFromAbbreviatedNames(HashSet abbreviatedNames)
+ {
+ // We must give each bot its own list of instantiated behaviours since they store state.
+ List behaviours = new List();
+
+ // Hard-coded for now
+ foreach (string abName in abbreviatedNames)
+ {
+ IBehaviour newBehaviour = null;
+
+ if (abName == "c")
+ newBehaviour = new CrossBehaviour();
+
+ if (abName == "g")
+ newBehaviour = new GrabbingBehaviour();
+
+ if (abName == "n")
+ newBehaviour = new NoneBehaviour();
+
+ if (abName == "p")
+ newBehaviour = new PhysicsBehaviour();
+
+ if (abName == "t")
+ newBehaviour = new TeleportBehaviour();
+
+ if (newBehaviour != null)
+ {
+ behaviours.Add(newBehaviour);
+ }
+ else
+ {
+ MainConsole.Instance.OutputFormat("No behaviour with abbreviated name {0} found", abName);
+ }
+ }
+
+ return behaviours;
+ }
+
public void ConnectBots(int botcount)
{
ConnectingBots = true;
@@ -453,6 +487,44 @@ namespace pCampBot
}
}
+ private void HandleAddBehaviour(string module, string[] cmd)
+ {
+ if (cmd.Length != 4)
+ {
+ MainConsole.Instance.OutputFormat("Usage: add behaviour ");
+ return;
+ }
+
+ string rawBehaviours = cmd[2];
+ int botNumber;
+
+ if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[3], out botNumber))
+ return;
+
+ Bot bot = GetBotFromNumber(botNumber);
+
+ if (bot == null)
+ {
+ MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
+ return;
+ }
+
+ HashSet rawAbbreviatedSwitchesToAdd = new HashSet();
+ Array.ForEach(rawBehaviours.Split(new char[] { ',' }), b => rawAbbreviatedSwitchesToAdd.Add(b));
+
+ List behavioursAdded = new List();
+
+ foreach (IBehaviour behaviour in CreateBehavioursFromAbbreviatedNames(rawAbbreviatedSwitchesToAdd))
+ {
+ if (bot.AddBehaviour(behaviour))
+ behavioursAdded.Add(behaviour);
+ }
+
+ MainConsole.Instance.OutputFormat(
+ "Added behaviours {0} to bot {1}",
+ string.Join(", ", behavioursAdded.ConvertAll(b => b.Name).ToArray()), bot.Name);
+ }
+
private void HandleDisconnect(string module, string[] cmd)
{
lock (m_bots)
@@ -594,7 +666,7 @@ namespace pCampBot
currentSim != null ? currentSim.Name : "(none)",
bot.ConnectionState,
bot.SimulatorsCount,
- string.Join(",", bot.Behaviours.ConvertAll(behaviour => behaviour.AbbreviatedName).ToArray()));
+ string.Join(",", bot.Behaviours.Keys.ToArray()));
}
}
@@ -621,16 +693,11 @@ namespace pCampBot
if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber))
return;
- string name = string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber);
-
- Bot bot;
-
- lock (m_bots)
- bot = m_bots.Find(b => b.Name == name);
+ Bot bot = GetBotFromNumber(botNumber);
if (bot == null)
{
- MainConsole.Instance.Output("No bot found with name {0}", name);
+ MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
return;
}
@@ -650,13 +717,39 @@ namespace pCampBot
MainConsole.Instance.Output("Settings");
ConsoleDisplayList statusCdl = new ConsoleDisplayList();
- statusCdl.AddRow("Behaviours", string.Join(", ", bot.Behaviours.ConvertAll(b => b.Name).ToArray()));
+
+ statusCdl.AddRow(
+ "Behaviours",
+ string.Join(", ", bot.Behaviours.Values.ToList().ConvertAll(b => b.Name).ToArray()));
+
GridClient botClient = bot.Client;
statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES);
MainConsole.Instance.Output(statusCdl.ToString());
}
+ ///
+ /// Get a specific bot from its number.
+ ///
+ /// null if no bot was found
+ ///
+ private Bot GetBotFromNumber(int botNumber)
+ {
+ string name = GenerateBotNameFromNumber(botNumber);
+
+ Bot bot;
+
+ lock (m_bots)
+ bot = m_bots.Find(b => b.Name == name);
+
+ return bot;
+ }
+
+ private string GenerateBotNameFromNumber(int botNumber)
+ {
+ return string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber);
+ }
+
internal void Grid_GridRegion(object o, GridRegionEventArgs args)
{
lock (RegionsKnown)