/* * 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; using System.Reflection; using System.Threading; using OpenMetaverse; using log4net; using log4net.Appender; using log4net.Core; using log4net.Repository; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; using pCampBot.Interfaces; namespace pCampBot { /// /// Thread/Bot manager for the application /// public class BotManager { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected CommandConsole m_console; protected List m_lBot; protected Random somthing = new Random(Environment.TickCount); public IConfig Config { get; private set; } /// /// Track the assets we have and have not received so we don't endlessly repeat requests. /// public Dictionary AssetsReceived { get; private set; } /// /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data /// public BotManager() { AssetsReceived = new Dictionary(); m_console = CreateConsole(); MainConsole.Instance = m_console; // Make log4net see the console // ILoggerRepository repository = LogManager.GetRepository(); IAppender[] appenders = repository.GetAppenders(); OpenSimAppender consoleAppender = null; foreach (IAppender appender in appenders) { if (appender.Name == "Console") { consoleAppender = (OpenSimAppender)appender; consoleAppender.Console = m_console; break; } } m_console.Commands.AddCommand("bot", false, "shutdown", "shutdown", "Shutdown bots and exit", HandleShutdown); m_console.Commands.AddCommand("bot", false, "quit", "quit", "Shutdown bots and exit", HandleShutdown); m_console.Commands.AddCommand("bot", false, "show status", "show status", "Shows the status of all bots", HandleShowStatus); // m_console.Commands.AddCommand("bot", false, "add bots", // "add bots ", // "Add more bots", HandleAddBots); m_lBot = new List(); } /// /// Startup number of bots specified in the starting arguments /// /// How many bots to start up /// The configuration for the bots to use public void dobotStartup(int botcount, IConfig cs) { Config = cs; string firstName = cs.GetString("firstname"); string lastNameStem = cs.GetString("lastname"); string password = cs.GetString("password"); string loginUri = cs.GetString("loginuri"); HashSet behaviourSwitches = new HashSet(); Array.ForEach( cs.GetString("behaviours", "p").Split(new char[] { ',' }), b => behaviourSwitches.Add(b)); for (int i = 0; i < botcount; i++) { string lastName = string.Format("{0}_{1}", lastNameStem, i); List behaviours = new List(); // Hard-coded for now if (behaviourSwitches.Contains("p")) behaviours.Add(new PhysicsBehaviour()); if (behaviourSwitches.Contains("g")) behaviours.Add(new GrabbingBehaviour()); startupBot(i, this, behaviours, firstName, lastName, password, loginUri); } } // /// // /// Add additional bots (and threads) to our bot pool // /// // /// How Many of them to add // public void addbots(int botcount) // { // int len = m_td.Length; // Thread[] m_td2 = new Thread[len + botcount]; // for (int i = 0; i < len; i++) // { // m_td2[i] = m_td[i]; // } // m_td = m_td2; // int newlen = len + botcount; // for (int i = len; i < newlen; i++) // { // startupBot(i, Config); // } // } /// /// This starts up the bot and stores the thread for the bot in the thread array /// /// The position in the thread array to stick the bot's thread /// /// Behaviours for this bot to perform. /// First name /// Last name /// Password /// Login URI public void startupBot( int pos, BotManager bm, List behaviours, string firstName, string lastName, string password, string loginUri) { Bot pb = new Bot(bm, behaviours, firstName, lastName, password, loginUri); pb.OnConnected += handlebotEvent; pb.OnDisconnected += handlebotEvent; lock (m_lBot) m_lBot.Add(pb); Thread pbThread = new Thread(pb.startup); pbThread.Name = pb.Name; pbThread.IsBackground = true; pbThread.Start(); } /// /// High level connnected/disconnected events so we can keep track of our threads by proxy /// /// /// private void handlebotEvent(Bot callbot, EventType eventt) { switch (eventt) { case EventType.CONNECTED: m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Connected"); break; case EventType.DISCONNECTED: m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Disconnected"); lock (m_lBot) { if (m_lBot.TrueForAll(b => !b.IsConnected)) Environment.Exit(0); break; } } } /// /// Shutting down all bots /// public void doBotShutdown() { lock (m_lBot) foreach (Bot pb in m_lBot) pb.shutdown(); } /// /// Standard CreateConsole routine /// /// protected CommandConsole CreateConsole() { return new LocalConsole("Region"); } private void HandleShutdown(string module, string[] cmd) { m_log.Warn("[BOTMANAGER]: Shutting down bots"); doBotShutdown(); } private void HandleShowStatus(string module, string[] cmd) { string outputFormat = "{0,-30} {1,-14}"; MainConsole.Instance.OutputFormat(outputFormat, "Name", "Status"); lock (m_lBot) { foreach (Bot pb in m_lBot) { MainConsole.Instance.OutputFormat( outputFormat, pb.Name, (pb.IsConnected ? "Connected" : "Disconnected")); } } } /* private void HandleQuit(string module, string[] cmd) { m_console.Warn("DANGER", "This should only be used to quit the program if you've already used the shutdown command and the program hasn't quit"); Environment.Exit(0); } */ // // private void HandleAddBots(string module, string[] cmd) // { // int newbots = 0; // // if (cmd.Length > 2) // { // Int32.TryParse(cmd[2], out newbots); // } // if (newbots > 0) // addbots(newbots); // } } }