diff options
author | Justin Clark-Casey (justincc) | 2013-09-03 18:51:55 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2013-09-03 18:51:55 +0100 |
commit | 9bd62715704685738c55c6de8127b16cc6695bdb (patch) | |
tree | 2e05a893e763f9d02484f341d50f023d738a43f5 /OpenSim/Tools | |
parent | And fix break in "show bot" from commit 9c65207 (diff) | |
download | opensim-SC-9bd62715704685738c55c6de8127b16cc6695bdb.zip opensim-SC-9bd62715704685738c55c6de8127b16cc6695bdb.tar.gz opensim-SC-9bd62715704685738c55c6de8127b16cc6695bdb.tar.bz2 opensim-SC-9bd62715704685738c55c6de8127b16cc6695bdb.tar.xz |
Add ability to adjust pCampbot bot behaviours whilst running with "add behaviour <behaviour-name> <bot-number>" console commad
Diffstat (limited to 'OpenSim/Tools')
-rw-r--r-- | OpenSim/Tools/pCampBot/Bot.cs | 51 | ||||
-rw-r--r-- | OpenSim/Tools/pCampBot/BotManager.cs | 147 |
2 files changed, 157 insertions, 41 deletions
diff --git a/OpenSim/Tools/pCampBot/Bot.cs b/OpenSim/Tools/pCampBot/Bot.cs index d418288..6037516 100644 --- a/OpenSim/Tools/pCampBot/Bot.cs +++ b/OpenSim/Tools/pCampBot/Bot.cs | |||
@@ -72,9 +72,10 @@ namespace pCampBot | |||
72 | /// Behaviours implemented by this bot. | 72 | /// Behaviours implemented by this bot. |
73 | /// </summary> | 73 | /// </summary> |
74 | /// <remarks> | 74 | /// <remarks> |
75 | /// Lock this list before manipulating it. | 75 | /// Indexed by abbreviated name. There can only be one instance of a particular behaviour. |
76 | /// Lock this structure before manipulating it. | ||
76 | /// </remarks> | 77 | /// </remarks> |
77 | public List<IBehaviour> Behaviours { get; private set; } | 78 | public Dictionary<string, IBehaviour> Behaviours { get; private set; } |
78 | 79 | ||
79 | /// <summary> | 80 | /// <summary> |
80 | /// Objects that the bot has discovered. | 81 | /// Objects that the bot has discovered. |
@@ -165,8 +166,6 @@ namespace pCampBot | |||
165 | { | 166 | { |
166 | ConnectionState = ConnectionState.Disconnected; | 167 | ConnectionState = ConnectionState.Disconnected; |
167 | 168 | ||
168 | behaviours.ForEach(b => b.Initialize(this)); | ||
169 | |||
170 | Random = new Random(Environment.TickCount);// We do stuff randomly here | 169 | Random = new Random(Environment.TickCount);// We do stuff randomly here |
171 | FirstName = firstName; | 170 | FirstName = firstName; |
172 | LastName = lastName; | 171 | LastName = lastName; |
@@ -176,12 +175,31 @@ namespace pCampBot | |||
176 | StartLocation = startLocation; | 175 | StartLocation = startLocation; |
177 | 176 | ||
178 | Manager = bm; | 177 | Manager = bm; |
179 | Behaviours = behaviours; | 178 | |
179 | Behaviours = new Dictionary<string, IBehaviour>(); | ||
180 | foreach (IBehaviour behaviour in behaviours) | ||
181 | AddBehaviour(behaviour); | ||
180 | 182 | ||
181 | // Only calling for use as a template. | 183 | // Only calling for use as a template. |
182 | CreateLibOmvClient(); | 184 | CreateLibOmvClient(); |
183 | } | 185 | } |
184 | 186 | ||
187 | public bool AddBehaviour(IBehaviour behaviour) | ||
188 | { | ||
189 | lock (Behaviours) | ||
190 | { | ||
191 | if (!Behaviours.ContainsKey(behaviour.AbbreviatedName)) | ||
192 | { | ||
193 | behaviour.Initialize(this); | ||
194 | Behaviours.Add(behaviour.AbbreviatedName, behaviour); | ||
195 | |||
196 | return true; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | return false; | ||
201 | } | ||
202 | |||
185 | private void CreateLibOmvClient() | 203 | private void CreateLibOmvClient() |
186 | { | 204 | { |
187 | GridClient newClient = new GridClient(); | 205 | GridClient newClient = new GridClient(); |
@@ -237,16 +255,21 @@ namespace pCampBot | |||
237 | private void Action() | 255 | private void Action() |
238 | { | 256 | { |
239 | while (ConnectionState != ConnectionState.Disconnecting) | 257 | while (ConnectionState != ConnectionState.Disconnecting) |
258 | { | ||
240 | lock (Behaviours) | 259 | lock (Behaviours) |
241 | Behaviours.ForEach( | 260 | { |
242 | b => | 261 | foreach (IBehaviour behaviour in Behaviours.Values) |
243 | { | 262 | { |
244 | Thread.Sleep(Random.Next(3000, 10000)); | 263 | Thread.Sleep(Random.Next(3000, 10000)); |
245 | 264 | ||
246 | // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType()); | 265 | // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType()); |
247 | b.Action(); | 266 | behaviour.Action(); |
248 | } | 267 | } |
249 | ); | 268 | } |
269 | |||
270 | // XXX: This is a really shitty way of yielding so that behaviours can be added/removed | ||
271 | Thread.Sleep(100); | ||
272 | } | ||
250 | } | 273 | } |
251 | 274 | ||
252 | /// <summary> | 275 | /// <summary> |
diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs index 3e446af..51c5ff4 100644 --- a/OpenSim/Tools/pCampBot/BotManager.cs +++ b/OpenSim/Tools/pCampBot/BotManager.cs | |||
@@ -140,7 +140,7 @@ namespace pCampBot | |||
140 | /// <summary> | 140 | /// <summary> |
141 | /// Behaviour switches for bots. | 141 | /// Behaviour switches for bots. |
142 | /// </summary> | 142 | /// </summary> |
143 | private HashSet<string> m_behaviourSwitches = new HashSet<string>(); | 143 | private HashSet<string> m_defaultBehaviourSwitches = new HashSet<string>(); |
144 | 144 | ||
145 | /// <summary> | 145 | /// <summary> |
146 | /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data | 146 | /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data |
@@ -195,6 +195,18 @@ namespace pCampBot | |||
195 | HandleDisconnect); | 195 | HandleDisconnect); |
196 | 196 | ||
197 | m_console.Commands.AddCommand( | 197 | m_console.Commands.AddCommand( |
198 | "bot", false, "add behaviour", "add behaviour <abbreviated-name> <bot-number>", | ||
199 | "Add a behaviour to a bot", | ||
200 | "Can be performed on connected or disconnected bots.", | ||
201 | HandleAddBehaviour); | ||
202 | |||
203 | // m_console.Commands.AddCommand( | ||
204 | // "bot", false, "remove behaviour", "remove behaviour <abbreviated-name> <bot-number>", | ||
205 | // "Remove a behaviour from a bot", | ||
206 | // "Can be performed on connected or disconnected bots.", | ||
207 | // HandleRemoveBehaviour); | ||
208 | |||
209 | m_console.Commands.AddCommand( | ||
198 | "bot", false, "sit", "sit", "Sit all bots on the ground.", | 210 | "bot", false, "sit", "sit", "Sit all bots on the ground.", |
199 | HandleSit); | 211 | HandleSit); |
200 | 212 | ||
@@ -235,7 +247,7 @@ namespace pCampBot | |||
235 | m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last")); | 247 | m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last")); |
236 | 248 | ||
237 | Array.ForEach<string>( | 249 | Array.ForEach<string>( |
238 | startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_behaviourSwitches.Add(b)); | 250 | startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_defaultBehaviourSwitches.Add(b)); |
239 | 251 | ||
240 | for (int i = 0; i < botcount; i++) | 252 | for (int i = 0; i < botcount; i++) |
241 | { | 253 | { |
@@ -243,28 +255,50 @@ namespace pCampBot | |||
243 | { | 255 | { |
244 | string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber); | 256 | string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber); |
245 | 257 | ||
246 | // We must give each bot its own list of instantiated behaviours since they store state. | 258 | CreateBot( |
247 | List<IBehaviour> behaviours = new List<IBehaviour>(); | 259 | this, |
248 | 260 | CreateBehavioursFromAbbreviatedNames(m_defaultBehaviourSwitches), | |
249 | // Hard-coded for now | 261 | m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting); |
250 | if (m_behaviourSwitches.Contains("c")) | 262 | } |
251 | behaviours.Add(new CrossBehaviour()); | 263 | } |
264 | } | ||
265 | |||
266 | private List<IBehaviour> CreateBehavioursFromAbbreviatedNames(HashSet<string> abbreviatedNames) | ||
267 | { | ||
268 | // We must give each bot its own list of instantiated behaviours since they store state. | ||
269 | List<IBehaviour> behaviours = new List<IBehaviour>(); | ||
270 | |||
271 | // Hard-coded for now | ||
272 | foreach (string abName in abbreviatedNames) | ||
273 | { | ||
274 | IBehaviour newBehaviour = null; | ||
275 | |||
276 | if (abName == "c") | ||
277 | newBehaviour = new CrossBehaviour(); | ||
278 | |||
279 | if (abName == "g") | ||
280 | newBehaviour = new GrabbingBehaviour(); | ||
252 | 281 | ||
253 | if (m_behaviourSwitches.Contains("g")) | 282 | if (abName == "n") |
254 | behaviours.Add(new GrabbingBehaviour()); | 283 | newBehaviour = new NoneBehaviour(); |
255 | 284 | ||
256 | if (m_behaviourSwitches.Contains("n")) | 285 | if (abName == "p") |
257 | behaviours.Add(new NoneBehaviour()); | 286 | newBehaviour = new PhysicsBehaviour(); |
258 | 287 | ||
259 | if (m_behaviourSwitches.Contains("p")) | 288 | if (abName == "t") |
260 | behaviours.Add(new PhysicsBehaviour()); | 289 | newBehaviour = new TeleportBehaviour(); |
261 | |||
262 | if (m_behaviourSwitches.Contains("t")) | ||
263 | behaviours.Add(new TeleportBehaviour()); | ||
264 | 290 | ||
265 | CreateBot(this, behaviours, m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting); | 291 | if (newBehaviour != null) |
292 | { | ||
293 | behaviours.Add(newBehaviour); | ||
294 | } | ||
295 | else | ||
296 | { | ||
297 | MainConsole.Instance.OutputFormat("No behaviour with abbreviated name {0} found", abName); | ||
266 | } | 298 | } |
267 | } | 299 | } |
300 | |||
301 | return behaviours; | ||
268 | } | 302 | } |
269 | 303 | ||
270 | public void ConnectBots(int botcount) | 304 | public void ConnectBots(int botcount) |
@@ -453,6 +487,44 @@ namespace pCampBot | |||
453 | } | 487 | } |
454 | } | 488 | } |
455 | 489 | ||
490 | private void HandleAddBehaviour(string module, string[] cmd) | ||
491 | { | ||
492 | if (cmd.Length != 4) | ||
493 | { | ||
494 | MainConsole.Instance.OutputFormat("Usage: add behaviour <abbreviated-behaviour> <bot-number>"); | ||
495 | return; | ||
496 | } | ||
497 | |||
498 | string rawBehaviours = cmd[2]; | ||
499 | int botNumber; | ||
500 | |||
501 | if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[3], out botNumber)) | ||
502 | return; | ||
503 | |||
504 | Bot bot = GetBotFromNumber(botNumber); | ||
505 | |||
506 | if (bot == null) | ||
507 | { | ||
508 | MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber); | ||
509 | return; | ||
510 | } | ||
511 | |||
512 | HashSet<string> rawAbbreviatedSwitchesToAdd = new HashSet<string>(); | ||
513 | Array.ForEach<string>(rawBehaviours.Split(new char[] { ',' }), b => rawAbbreviatedSwitchesToAdd.Add(b)); | ||
514 | |||
515 | List<IBehaviour> behavioursAdded = new List<IBehaviour>(); | ||
516 | |||
517 | foreach (IBehaviour behaviour in CreateBehavioursFromAbbreviatedNames(rawAbbreviatedSwitchesToAdd)) | ||
518 | { | ||
519 | if (bot.AddBehaviour(behaviour)) | ||
520 | behavioursAdded.Add(behaviour); | ||
521 | } | ||
522 | |||
523 | MainConsole.Instance.OutputFormat( | ||
524 | "Added behaviours {0} to bot {1}", | ||
525 | string.Join(", ", behavioursAdded.ConvertAll<string>(b => b.Name).ToArray()), bot.Name); | ||
526 | } | ||
527 | |||
456 | private void HandleDisconnect(string module, string[] cmd) | 528 | private void HandleDisconnect(string module, string[] cmd) |
457 | { | 529 | { |
458 | lock (m_bots) | 530 | lock (m_bots) |
@@ -594,7 +666,7 @@ namespace pCampBot | |||
594 | currentSim != null ? currentSim.Name : "(none)", | 666 | currentSim != null ? currentSim.Name : "(none)", |
595 | bot.ConnectionState, | 667 | bot.ConnectionState, |
596 | bot.SimulatorsCount, | 668 | bot.SimulatorsCount, |
597 | string.Join(",", bot.Behaviours.ConvertAll<string>(behaviour => behaviour.AbbreviatedName).ToArray())); | 669 | string.Join(",", bot.Behaviours.Keys.ToArray())); |
598 | } | 670 | } |
599 | } | 671 | } |
600 | 672 | ||
@@ -621,16 +693,11 @@ namespace pCampBot | |||
621 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber)) | 693 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber)) |
622 | return; | 694 | return; |
623 | 695 | ||
624 | string name = string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber); | 696 | Bot bot = GetBotFromNumber(botNumber); |
625 | |||
626 | Bot bot; | ||
627 | |||
628 | lock (m_bots) | ||
629 | bot = m_bots.Find(b => b.Name == name); | ||
630 | 697 | ||
631 | if (bot == null) | 698 | if (bot == null) |
632 | { | 699 | { |
633 | MainConsole.Instance.Output("No bot found with name {0}", name); | 700 | MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber); |
634 | return; | 701 | return; |
635 | } | 702 | } |
636 | 703 | ||
@@ -650,13 +717,39 @@ namespace pCampBot | |||
650 | MainConsole.Instance.Output("Settings"); | 717 | MainConsole.Instance.Output("Settings"); |
651 | 718 | ||
652 | ConsoleDisplayList statusCdl = new ConsoleDisplayList(); | 719 | ConsoleDisplayList statusCdl = new ConsoleDisplayList(); |
653 | statusCdl.AddRow("Behaviours", string.Join(", ", bot.Behaviours.ConvertAll<string>(b => b.Name).ToArray())); | 720 | |
721 | statusCdl.AddRow( | ||
722 | "Behaviours", | ||
723 | string.Join(", ", bot.Behaviours.Values.ToList().ConvertAll<string>(b => b.Name).ToArray())); | ||
724 | |||
654 | GridClient botClient = bot.Client; | 725 | GridClient botClient = bot.Client; |
655 | statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES); | 726 | statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES); |
656 | 727 | ||
657 | MainConsole.Instance.Output(statusCdl.ToString()); | 728 | MainConsole.Instance.Output(statusCdl.ToString()); |
658 | } | 729 | } |
659 | 730 | ||
731 | /// <summary> | ||
732 | /// Get a specific bot from its number. | ||
733 | /// </summary> | ||
734 | /// <returns>null if no bot was found</returns> | ||
735 | /// <param name='botNumber'></param> | ||
736 | private Bot GetBotFromNumber(int botNumber) | ||
737 | { | ||
738 | string name = GenerateBotNameFromNumber(botNumber); | ||
739 | |||
740 | Bot bot; | ||
741 | |||
742 | lock (m_bots) | ||
743 | bot = m_bots.Find(b => b.Name == name); | ||
744 | |||
745 | return bot; | ||
746 | } | ||
747 | |||
748 | private string GenerateBotNameFromNumber(int botNumber) | ||
749 | { | ||
750 | return string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber); | ||
751 | } | ||
752 | |||
660 | internal void Grid_GridRegion(object o, GridRegionEventArgs args) | 753 | internal void Grid_GridRegion(object o, GridRegionEventArgs args) |
661 | { | 754 | { |
662 | lock (RegionsKnown) | 755 | lock (RegionsKnown) |