diff options
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 12 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneBase.cs | 13 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 14 | ||||
-rw-r--r-- | OpenSim/Tools/pCampBot/Bot.cs | 33 | ||||
-rw-r--r-- | OpenSim/Tools/pCampBot/BotManager.cs | 103 | ||||
-rw-r--r-- | OpenSim/Tools/pCampBot/pCampBot.cs | 72 | ||||
-rw-r--r-- | bin/pCampbot.ini.example | 15 |
7 files changed, 192 insertions, 70 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 6323a88..4fa4a7c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -3540,6 +3540,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
3540 | } | 3540 | } |
3541 | } | 3541 | } |
3542 | 3542 | ||
3543 | /// <summary> | ||
3544 | /// Remove the given client from the scene. | ||
3545 | /// </summary> | ||
3546 | /// <remarks> | ||
3547 | /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead | ||
3548 | /// to properly operate the state machine and avoid race conditions with other close requests (such as directly | ||
3549 | /// from viewers). | ||
3550 | /// </remarks> | ||
3551 | /// <param name='agentID'>ID of agent to close</param> | ||
3552 | /// <param name='closeChildAgents'> | ||
3553 | /// Close the neighbour child agents associated with this client. | ||
3554 | /// </param> | ||
3543 | public override void RemoveClient(UUID agentID, bool closeChildAgents) | 3555 | public override void RemoveClient(UUID agentID, bool closeChildAgents) |
3544 | { | 3556 | { |
3545 | AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); | 3557 | AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); |
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 4eef162..1dac676 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs | |||
@@ -218,6 +218,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
218 | #region Add/Remove Agent/Avatar | 218 | #region Add/Remove Agent/Avatar |
219 | 219 | ||
220 | public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); | 220 | public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); |
221 | |||
222 | /// <summary> | ||
223 | /// Remove the given client from the scene. | ||
224 | /// </summary> | ||
225 | /// <remarks> | ||
226 | /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead | ||
227 | /// to properly operate the state machine and avoid race conditions with other close requests (such as directly | ||
228 | /// from viewers). | ||
229 | /// </remarks> | ||
230 | /// <param name='agentID'>ID of agent to close</param> | ||
231 | /// <param name='closeChildAgents'> | ||
232 | /// Close the neighbour child agents associated with this client. | ||
233 | /// </param> | ||
221 | public abstract void RemoveClient(UUID agentID, bool closeChildAgents); | 234 | public abstract void RemoveClient(UUID agentID, bool closeChildAgents); |
222 | 235 | ||
223 | public bool TryGetScenePresence(UUID agentID, out object scenePresence) | 236 | public bool TryGetScenePresence(UUID agentID, out object scenePresence) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index d584782..502f85f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -89,13 +89,6 @@ public sealed class BSCharacter : BSPhysObject | |||
89 | // set _avatarVolume and _mass based on capsule size, _density and Scale | 89 | // set _avatarVolume and _mass based on capsule size, _density and Scale |
90 | ComputeAvatarVolumeAndMass(); | 90 | ComputeAvatarVolumeAndMass(); |
91 | 91 | ||
92 | // The avatar's movement is controlled by this motor that speeds up and slows down | ||
93 | // the avatar seeking to reach the motor's target speed. | ||
94 | // This motor runs as a prestep action for the avatar so it will keep the avatar | ||
95 | // standing as well as moving. Destruction of the avatar will destroy the pre-step action. | ||
96 | m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName); | ||
97 | PhysicalActors.Add(AvatarMoveActorName, m_moveActor); | ||
98 | |||
99 | DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5},pos={6}", | 92 | DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5},pos={6}", |
100 | LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos); | 93 | LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos); |
101 | 94 | ||
@@ -106,6 +99,13 @@ public sealed class BSCharacter : BSPhysObject | |||
106 | // New body and shape into PhysBody and PhysShape | 99 | // New body and shape into PhysBody and PhysShape |
107 | PhysScene.Shapes.GetBodyAndShape(true, PhysScene.World, this); | 100 | PhysScene.Shapes.GetBodyAndShape(true, PhysScene.World, this); |
108 | 101 | ||
102 | // The avatar's movement is controlled by this motor that speeds up and slows down | ||
103 | // the avatar seeking to reach the motor's target speed. | ||
104 | // This motor runs as a prestep action for the avatar so it will keep the avatar | ||
105 | // standing as well as moving. Destruction of the avatar will destroy the pre-step action. | ||
106 | m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName); | ||
107 | PhysicalActors.Add(AvatarMoveActorName, m_moveActor); | ||
108 | |||
109 | SetPhysicalProperties(); | 109 | SetPhysicalProperties(); |
110 | }); | 110 | }); |
111 | return; | 111 | return; |
diff --git a/OpenSim/Tools/pCampBot/Bot.cs b/OpenSim/Tools/pCampBot/Bot.cs index 9821180..dac8ccb 100644 --- a/OpenSim/Tools/pCampBot/Bot.cs +++ b/OpenSim/Tools/pCampBot/Bot.cs | |||
@@ -64,11 +64,6 @@ namespace pCampBot | |||
64 | public BotManager Manager { get; private set; } | 64 | public BotManager Manager { get; private set; } |
65 | 65 | ||
66 | /// <summary> | 66 | /// <summary> |
67 | /// Bot config, passed from BotManager. | ||
68 | /// </summary> | ||
69 | private IConfig startupConfig; | ||
70 | |||
71 | /// <summary> | ||
72 | /// Behaviours implemented by this bot. | 67 | /// Behaviours implemented by this bot. |
73 | /// </summary> | 68 | /// </summary> |
74 | /// <remarks> | 69 | /// <remarks> |
@@ -102,6 +97,8 @@ namespace pCampBot | |||
102 | public string Name { get; private set; } | 97 | public string Name { get; private set; } |
103 | public string Password { get; private set; } | 98 | public string Password { get; private set; } |
104 | public string LoginUri { get; private set; } | 99 | public string LoginUri { get; private set; } |
100 | public string StartLocation { get; private set; } | ||
101 | |||
105 | public string saveDir; | 102 | public string saveDir; |
106 | public string wear; | 103 | public string wear; |
107 | 104 | ||
@@ -137,7 +134,7 @@ namespace pCampBot | |||
137 | /// <param name="behaviours"></param> | 134 | /// <param name="behaviours"></param> |
138 | public Bot( | 135 | public Bot( |
139 | BotManager bm, List<IBehaviour> behaviours, | 136 | BotManager bm, List<IBehaviour> behaviours, |
140 | string firstName, string lastName, string password, string loginUri) | 137 | string firstName, string lastName, string password, string startLocation, string loginUri) |
141 | { | 138 | { |
142 | ConnectionState = ConnectionState.Disconnected; | 139 | ConnectionState = ConnectionState.Disconnected; |
143 | 140 | ||
@@ -151,11 +148,9 @@ namespace pCampBot | |||
151 | Name = string.Format("{0} {1}", FirstName, LastName); | 148 | Name = string.Format("{0} {1}", FirstName, LastName); |
152 | Password = password; | 149 | Password = password; |
153 | LoginUri = loginUri; | 150 | LoginUri = loginUri; |
151 | StartLocation = startLocation; | ||
154 | 152 | ||
155 | Manager = bm; | 153 | Manager = bm; |
156 | startupConfig = bm.Config; | ||
157 | readconfig(); | ||
158 | |||
159 | Behaviours = behaviours; | 154 | Behaviours = behaviours; |
160 | } | 155 | } |
161 | 156 | ||
@@ -163,7 +158,7 @@ namespace pCampBot | |||
163 | //add additional steps and/or things the bot should do | 158 | //add additional steps and/or things the bot should do |
164 | private void Action() | 159 | private void Action() |
165 | { | 160 | { |
166 | while (true) | 161 | while (ConnectionState != ConnectionState.Disconnecting) |
167 | lock (Behaviours) | 162 | lock (Behaviours) |
168 | Behaviours.ForEach( | 163 | Behaviours.ForEach( |
169 | b => | 164 | b => |
@@ -177,22 +172,14 @@ namespace pCampBot | |||
177 | } | 172 | } |
178 | 173 | ||
179 | /// <summary> | 174 | /// <summary> |
180 | /// Read the Nini config and initialize | ||
181 | /// </summary> | ||
182 | public void readconfig() | ||
183 | { | ||
184 | wear = startupConfig.GetString("wear", "no"); | ||
185 | } | ||
186 | |||
187 | /// <summary> | ||
188 | /// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes. | 175 | /// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes. |
189 | /// </summary> | 176 | /// </summary> |
190 | public void shutdown() | 177 | public void shutdown() |
191 | { | 178 | { |
192 | ConnectionState = ConnectionState.Disconnecting; | 179 | ConnectionState = ConnectionState.Disconnecting; |
193 | 180 | ||
194 | if (m_actionThread != null) | 181 | // if (m_actionThread != null) |
195 | m_actionThread.Abort(); | 182 | // m_actionThread.Abort(); |
196 | 183 | ||
197 | Client.Network.Logout(); | 184 | Client.Network.Logout(); |
198 | } | 185 | } |
@@ -207,6 +194,7 @@ namespace pCampBot | |||
207 | Client.Settings.AVATAR_TRACKING = false; | 194 | Client.Settings.AVATAR_TRACKING = false; |
208 | Client.Settings.OBJECT_TRACKING = false; | 195 | Client.Settings.OBJECT_TRACKING = false; |
209 | Client.Settings.SEND_AGENT_THROTTLE = true; | 196 | Client.Settings.SEND_AGENT_THROTTLE = true; |
197 | Client.Settings.SEND_AGENT_UPDATES = false; | ||
210 | Client.Settings.SEND_PINGS = true; | 198 | Client.Settings.SEND_PINGS = true; |
211 | Client.Settings.STORE_LAND_PATCHES = false; | 199 | Client.Settings.STORE_LAND_PATCHES = false; |
212 | Client.Settings.USE_ASSET_CACHE = false; | 200 | Client.Settings.USE_ASSET_CACHE = false; |
@@ -224,7 +212,7 @@ namespace pCampBot | |||
224 | 212 | ||
225 | ConnectionState = ConnectionState.Connecting; | 213 | ConnectionState = ConnectionState.Connecting; |
226 | 214 | ||
227 | if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", "Your name")) | 215 | if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", StartLocation, "Your name")) |
228 | { | 216 | { |
229 | ConnectionState = ConnectionState.Connected; | 217 | ConnectionState = ConnectionState.Connected; |
230 | 218 | ||
@@ -481,9 +469,6 @@ namespace pCampBot | |||
481 | 469 | ||
482 | public void Objects_NewPrim(object sender, PrimEventArgs args) | 470 | public void Objects_NewPrim(object sender, PrimEventArgs args) |
483 | { | 471 | { |
484 | // if (Name.EndsWith("4")) | ||
485 | // throw new Exception("Aaargh"); | ||
486 | |||
487 | Primitive prim = args.Prim; | 472 | Primitive prim = args.Prim; |
488 | 473 | ||
489 | if (prim != null) | 474 | if (prim != null) |
diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs index 74bd36a..397a98e 100644 --- a/OpenSim/Tools/pCampBot/BotManager.cs +++ b/OpenSim/Tools/pCampBot/BotManager.cs | |||
@@ -52,6 +52,11 @@ namespace pCampBot | |||
52 | public const int DefaultLoginDelay = 5000; | 52 | public const int DefaultLoginDelay = 5000; |
53 | 53 | ||
54 | /// <summary> | 54 | /// <summary> |
55 | /// True if pCampbot is in the process of shutting down. | ||
56 | /// </summary> | ||
57 | public bool ShuttingDown { get; private set; } | ||
58 | |||
59 | /// <summary> | ||
55 | /// Delay between logins of multiple bots. | 60 | /// Delay between logins of multiple bots. |
56 | /// </summary> | 61 | /// </summary> |
57 | /// <remarks>TODO: This value needs to be configurable by a command line argument.</remarks> | 62 | /// <remarks>TODO: This value needs to be configurable by a command line argument.</remarks> |
@@ -63,6 +68,16 @@ namespace pCampBot | |||
63 | protected CommandConsole m_console; | 68 | protected CommandConsole m_console; |
64 | 69 | ||
65 | /// <summary> | 70 | /// <summary> |
71 | /// Controls whether bots start out sending agent updates on connection. | ||
72 | /// </summary> | ||
73 | public bool InitBotSendAgentUpdates { get; set; } | ||
74 | |||
75 | /// <summary> | ||
76 | /// Controls whether bots request textures for the object information they receive | ||
77 | /// </summary> | ||
78 | public bool InitBotRequestObjectTextures { get; set; } | ||
79 | |||
80 | /// <summary> | ||
66 | /// Created bots, whether active or inactive. | 81 | /// Created bots, whether active or inactive. |
67 | /// </summary> | 82 | /// </summary> |
68 | protected List<Bot> m_lBot; | 83 | protected List<Bot> m_lBot; |
@@ -73,11 +88,6 @@ namespace pCampBot | |||
73 | public Random Rng { get; private set; } | 88 | public Random Rng { get; private set; } |
74 | 89 | ||
75 | /// <summary> | 90 | /// <summary> |
76 | /// Overall configuration. | ||
77 | /// </summary> | ||
78 | public IConfig Config { get; private set; } | ||
79 | |||
80 | /// <summary> | ||
81 | /// Track the assets we have and have not received so we don't endlessly repeat requests. | 91 | /// Track the assets we have and have not received so we don't endlessly repeat requests. |
82 | /// </summary> | 92 | /// </summary> |
83 | public Dictionary<UUID, bool> AssetsReceived { get; private set; } | 93 | public Dictionary<UUID, bool> AssetsReceived { get; private set; } |
@@ -92,6 +102,9 @@ namespace pCampBot | |||
92 | /// </summary> | 102 | /// </summary> |
93 | public BotManager() | 103 | public BotManager() |
94 | { | 104 | { |
105 | InitBotSendAgentUpdates = true; | ||
106 | InitBotRequestObjectTextures = true; | ||
107 | |||
95 | LoginDelay = DefaultLoginDelay; | 108 | LoginDelay = DefaultLoginDelay; |
96 | 109 | ||
97 | Rng = new Random(Environment.TickCount); | 110 | Rng = new Random(Environment.TickCount); |
@@ -148,31 +161,40 @@ namespace pCampBot | |||
148 | /// </summary> | 161 | /// </summary> |
149 | /// <param name="botcount">How many bots to start up</param> | 162 | /// <param name="botcount">How many bots to start up</param> |
150 | /// <param name="cs">The configuration for the bots to use</param> | 163 | /// <param name="cs">The configuration for the bots to use</param> |
151 | public void dobotStartup(int botcount, IConfig cs) | 164 | public void dobotStartup(int botcount, IConfig startupConfig) |
152 | { | 165 | { |
153 | Config = cs; | 166 | string firstName = startupConfig.GetString("firstname"); |
167 | string lastNameStem = startupConfig.GetString("lastname"); | ||
168 | string password = startupConfig.GetString("password"); | ||
169 | string loginUri = startupConfig.GetString("loginuri"); | ||
170 | string startLocation = startupConfig.GetString("start", "last"); | ||
171 | int fromBotNumber = startupConfig.GetInt("from", 0); | ||
172 | string wearSetting = startupConfig.GetString("wear", "no"); | ||
154 | 173 | ||
155 | string firstName = cs.GetString("firstname"); | 174 | string startUri = ParseInputStartLocationToUri(startLocation); |
156 | string lastNameStem = cs.GetString("lastname"); | ||
157 | string password = cs.GetString("password"); | ||
158 | string loginUri = cs.GetString("loginuri"); | ||
159 | 175 | ||
160 | HashSet<string> behaviourSwitches = new HashSet<string>(); | 176 | HashSet<string> behaviourSwitches = new HashSet<string>(); |
161 | Array.ForEach<string>( | 177 | Array.ForEach<string>( |
162 | cs.GetString("behaviours", "p").Split(new char[] { ',' }), b => behaviourSwitches.Add(b)); | 178 | startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => behaviourSwitches.Add(b)); |
163 | 179 | ||
164 | MainConsole.Instance.OutputFormat( | 180 | MainConsole.Instance.OutputFormat( |
165 | "[BOT MANAGER]: Starting {0} bots connecting to {1}, named {2} {3}_<n>", | 181 | "[BOT MANAGER]: Starting {0} bots connecting to {1}, location {2}, named {3} {4}_<n>", |
166 | botcount, | 182 | botcount, |
167 | loginUri, | 183 | loginUri, |
184 | startUri, | ||
168 | firstName, | 185 | firstName, |
169 | lastNameStem); | 186 | lastNameStem); |
170 | 187 | ||
171 | MainConsole.Instance.OutputFormat("[BOT MANAGER]: Delay between logins is {0}ms", LoginDelay); | 188 | MainConsole.Instance.OutputFormat("[BOT MANAGER]: Delay between logins is {0}ms", LoginDelay); |
189 | MainConsole.Instance.OutputFormat("[BOT MANAGER]: BotsSendAgentUpdates is {0}", InitBotSendAgentUpdates); | ||
190 | MainConsole.Instance.OutputFormat("[BOT MANAGER]: InitBotRequestObjectTextures is {0}", InitBotRequestObjectTextures); | ||
172 | 191 | ||
173 | for (int i = 0; i < botcount; i++) | 192 | for (int i = 0; i < botcount; i++) |
174 | { | 193 | { |
175 | string lastName = string.Format("{0}_{1}", lastNameStem, i); | 194 | if (ShuttingDown) |
195 | break; | ||
196 | |||
197 | string lastName = string.Format("{0}_{1}", lastNameStem, i + fromBotNumber); | ||
176 | 198 | ||
177 | // We must give each bot its own list of instantiated behaviours since they store state. | 199 | // We must give each bot its own list of instantiated behaviours since they store state. |
178 | List<IBehaviour> behaviours = new List<IBehaviour>(); | 200 | List<IBehaviour> behaviours = new List<IBehaviour>(); |
@@ -193,10 +215,49 @@ namespace pCampBot | |||
193 | if (behaviourSwitches.Contains("t")) | 215 | if (behaviourSwitches.Contains("t")) |
194 | behaviours.Add(new TeleportBehaviour()); | 216 | behaviours.Add(new TeleportBehaviour()); |
195 | 217 | ||
196 | StartBot(this, behaviours, firstName, lastName, password, loginUri); | 218 | StartBot(this, behaviours, firstName, lastName, password, loginUri, startUri, wearSetting); |
197 | } | 219 | } |
198 | } | 220 | } |
199 | 221 | ||
222 | /// <summary> | ||
223 | /// Parses the command line start location to a start string/uri that the login mechanism will recognize. | ||
224 | /// </summary> | ||
225 | /// <returns> | ||
226 | /// The input start location to URI. | ||
227 | /// </returns> | ||
228 | /// <param name='startLocation'> | ||
229 | /// Start location. | ||
230 | /// </param> | ||
231 | private string ParseInputStartLocationToUri(string startLocation) | ||
232 | { | ||
233 | if (startLocation == "home" || startLocation == "last") | ||
234 | return startLocation; | ||
235 | |||
236 | string regionName; | ||
237 | |||
238 | // Just a region name or only one (!) extra component. Like a viewer, we will stick 128/128/0 on the end | ||
239 | Vector3 startPos = new Vector3(128, 128, 0); | ||
240 | |||
241 | string[] startLocationComponents = startLocation.Split('/'); | ||
242 | |||
243 | regionName = startLocationComponents[0]; | ||
244 | |||
245 | if (startLocationComponents.Length >= 2) | ||
246 | { | ||
247 | float.TryParse(startLocationComponents[1], out startPos.X); | ||
248 | |||
249 | if (startLocationComponents.Length >= 3) | ||
250 | { | ||
251 | float.TryParse(startLocationComponents[2], out startPos.Y); | ||
252 | |||
253 | if (startLocationComponents.Length >= 4) | ||
254 | float.TryParse(startLocationComponents[3], out startPos.Z); | ||
255 | } | ||
256 | } | ||
257 | |||
258 | return string.Format("uri:{0}&{1}&{2}&{3}", regionName, startPos.X, startPos.Y, startPos.Z); | ||
259 | } | ||
260 | |||
200 | // /// <summary> | 261 | // /// <summary> |
201 | // /// Add additional bots (and threads) to our bot pool | 262 | // /// Add additional bots (and threads) to our bot pool |
202 | // /// </summary> | 263 | // /// </summary> |
@@ -226,15 +287,19 @@ namespace pCampBot | |||
226 | /// <param name="lastName">Last name</param> | 287 | /// <param name="lastName">Last name</param> |
227 | /// <param name="password">Password</param> | 288 | /// <param name="password">Password</param> |
228 | /// <param name="loginUri">Login URI</param> | 289 | /// <param name="loginUri">Login URI</param> |
290 | /// <param name="startLocation">Location to start the bot. Can be "last", "home" or a specific sim name.</param> | ||
291 | /// <param name="wearSetting"></param> | ||
229 | public void StartBot( | 292 | public void StartBot( |
230 | BotManager bm, List<IBehaviour> behaviours, | 293 | BotManager bm, List<IBehaviour> behaviours, |
231 | string firstName, string lastName, string password, string loginUri) | 294 | string firstName, string lastName, string password, string loginUri, string startLocation, string wearSetting) |
232 | { | 295 | { |
233 | MainConsole.Instance.OutputFormat( | 296 | MainConsole.Instance.OutputFormat( |
234 | "[BOT MANAGER]: Starting bot {0} {1}, behaviours are {2}", | 297 | "[BOT MANAGER]: Starting bot {0} {1}, behaviours are {2}", |
235 | firstName, lastName, string.Join(",", behaviours.ConvertAll<string>(b => b.Name).ToArray())); | 298 | firstName, lastName, string.Join(",", behaviours.ConvertAll<string>(b => b.Name).ToArray())); |
236 | 299 | ||
237 | Bot pb = new Bot(bm, behaviours, firstName, lastName, password, loginUri); | 300 | Bot pb = new Bot(bm, behaviours, firstName, lastName, password, startLocation, loginUri); |
301 | pb.wear = wearSetting; | ||
302 | pb.Client.Settings.SEND_AGENT_UPDATES = InitBotSendAgentUpdates; | ||
238 | 303 | ||
239 | pb.OnConnected += handlebotEvent; | 304 | pb.OnConnected += handlebotEvent; |
240 | pb.OnDisconnected += handlebotEvent; | 305 | pb.OnDisconnected += handlebotEvent; |
@@ -306,7 +371,9 @@ namespace pCampBot | |||
306 | 371 | ||
307 | private void HandleShutdown(string module, string[] cmd) | 372 | private void HandleShutdown(string module, string[] cmd) |
308 | { | 373 | { |
309 | m_log.Info("[BOTMANAGER]: Shutting down bots"); | 374 | MainConsole.Instance.Output("Shutting down"); |
375 | |||
376 | ShuttingDown = true; | ||
310 | doBotShutdown(); | 377 | doBotShutdown(); |
311 | } | 378 | } |
312 | 379 | ||
diff --git a/OpenSim/Tools/pCampBot/pCampBot.cs b/OpenSim/Tools/pCampBot/pCampBot.cs index 2707a49..b02f917 100644 --- a/OpenSim/Tools/pCampBot/pCampBot.cs +++ b/OpenSim/Tools/pCampBot/pCampBot.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.IO; | ||
29 | using System.Reflection; | 30 | using System.Reflection; |
30 | using System.Threading; | 31 | using System.Threading; |
31 | using log4net; | 32 | using log4net; |
@@ -50,28 +51,52 @@ namespace pCampBot | |||
50 | { | 51 | { |
51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
52 | 53 | ||
54 | public const string ConfigFileName = "pCampbot.ini"; | ||
55 | |||
53 | [STAThread] | 56 | [STAThread] |
54 | public static void Main(string[] args) | 57 | public static void Main(string[] args) |
55 | { | 58 | { |
56 | XmlConfigurator.Configure(); | 59 | XmlConfigurator.Configure(); |
57 | 60 | ||
58 | IConfig config = ParseConfig(args); | 61 | IConfig commandLineConfig = ParseConfig(args); |
59 | if (config.Get("help") != null || config.Get("loginuri") == null) | 62 | if (commandLineConfig.Get("help") != null || commandLineConfig.Get("loginuri") == null) |
60 | { | 63 | { |
61 | Help(); | 64 | Help(); |
62 | } | 65 | } |
63 | else if (config.Get("firstname") == null || config.Get("lastname") == null || config.Get("password") == null) | 66 | else if ( |
67 | commandLineConfig.Get("firstname") == null | ||
68 | || commandLineConfig.Get("lastname") == null | ||
69 | || commandLineConfig.Get("password") == null) | ||
64 | { | 70 | { |
65 | Console.WriteLine("ERROR: You must supply a firstname, lastname and password for the bots."); | 71 | Console.WriteLine("ERROR: You must supply a firstname, lastname and password for the bots."); |
66 | } | 72 | } |
67 | else | 73 | else |
68 | { | 74 | { |
69 | int botcount = config.GetInt("botcount", 1); | ||
70 | |||
71 | BotManager bm = new BotManager(); | 75 | BotManager bm = new BotManager(); |
72 | 76 | ||
77 | string iniFilePath = Path.GetFullPath(Path.Combine(Util.configDir(), ConfigFileName)); | ||
78 | |||
79 | if (File.Exists(iniFilePath)) | ||
80 | { | ||
81 | m_log.InfoFormat("[PCAMPBOT]: Reading configuration settings from {0}", iniFilePath); | ||
82 | |||
83 | IConfigSource configSource = new IniConfigSource(iniFilePath); | ||
84 | |||
85 | IConfig botConfig = configSource.Configs["Bot"]; | ||
86 | |||
87 | if (botConfig != null) | ||
88 | { | ||
89 | bm.InitBotSendAgentUpdates | ||
90 | = botConfig.GetBoolean("SendAgentUpdates", bm.InitBotSendAgentUpdates); | ||
91 | bm.InitBotRequestObjectTextures | ||
92 | = botConfig.GetBoolean("RequestObjectTextures", bm.InitBotRequestObjectTextures); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | int botcount = commandLineConfig.GetInt("botcount", 1); | ||
97 | |||
73 | //startup specified number of bots. 1 is the default | 98 | //startup specified number of bots. 1 is the default |
74 | Thread startBotThread = new Thread(o => bm.dobotStartup(botcount, config)); | 99 | Thread startBotThread = new Thread(o => bm.dobotStartup(botcount, commandLineConfig)); |
75 | startBotThread.Name = "Initial start bots thread"; | 100 | startBotThread.Name = "Initial start bots thread"; |
76 | startBotThread.Start(); | 101 | startBotThread.Start(); |
77 | 102 | ||
@@ -95,7 +120,9 @@ namespace pCampBot | |||
95 | ArgvConfigSource cs = new ArgvConfigSource(args); | 120 | ArgvConfigSource cs = new ArgvConfigSource(args); |
96 | 121 | ||
97 | cs.AddSwitch("Startup", "botcount", "n"); | 122 | cs.AddSwitch("Startup", "botcount", "n"); |
123 | cs.AddSwitch("Startup", "from", "f"); | ||
98 | cs.AddSwitch("Startup", "loginuri", "l"); | 124 | cs.AddSwitch("Startup", "loginuri", "l"); |
125 | cs.AddSwitch("Startup", "start", "s"); | ||
99 | cs.AddSwitch("Startup", "firstname"); | 126 | cs.AddSwitch("Startup", "firstname"); |
100 | cs.AddSwitch("Startup", "lastname"); | 127 | cs.AddSwitch("Startup", "lastname"); |
101 | cs.AddSwitch("Startup", "password"); | 128 | cs.AddSwitch("Startup", "password"); |
@@ -113,23 +140,26 @@ namespace pCampBot | |||
113 | // You can either say no, to not load anything, yes, to load one of the default wearables, a folder | 140 | // You can either say no, to not load anything, yes, to load one of the default wearables, a folder |
114 | // name, to load an specific folder, or save, to save an avatar with some already existing wearables | 141 | // name, to load an specific folder, or save, to save an avatar with some already existing wearables |
115 | // worn to the folder MyAppearance/FirstName_LastName, and the load it. | 142 | // worn to the folder MyAppearance/FirstName_LastName, and the load it. |
143 | |||
116 | Console.WriteLine( | 144 | Console.WriteLine( |
117 | "usage: pCampBot <-loginuri loginuri> [OPTIONS]\n" + | 145 | "usage: pCampBot <-loginuri loginuri> [OPTIONS]\n" |
118 | "Spawns a set of bots to test an OpenSim region\n\n" + | 146 | + "Spawns a set of bots to test an OpenSim region\n\n" |
119 | " -l, -loginuri loginuri for sim to log into (required)\n" + | 147 | + " -l, -loginuri loginuri for grid/standalone (required)\n" |
120 | " -n, -botcount number of bots to start (default: 1)\n" + | 148 | + " -s, -start optional start location for bots. Can be \"last\", \"home\" or a specific location with or without co-ords (e.g. \"region1\" or \"region2/50/30/90\"\n" |
121 | " -firstname first name for the bots\n" + | 149 | + " -firstname first name for the bots\n" |
122 | " -lastname lastname for the bots. Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n" + | 150 | + " -lastname lastname for the bots. Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n" |
123 | " -password password for the bots\n" + | 151 | + " -password password for the bots\n" |
124 | " -b, behaviours behaviours for bots. Comma separated, e.g. p,g. Default is p\n" + | 152 | + " -n, -botcount optional number of bots to start (default: 1)\n" |
125 | " current options are:\n" + | 153 | + " -f, -from optional starting number for login bot names, e.g. 25 will login Ima Bot_25, Ima Bot_26, etc. (default: 0)" |
126 | " p (physics - bots constantly move and jump around)\n" + | 154 | + " -b, behaviours behaviours for bots. Comma separated, e.g. p,g. Default is p\n" |
127 | " g (grab - bots randomly click prims whether set clickable or not)\n" + | 155 | + " current options are:\n" |
128 | " n (none - bots do nothing)\n" + | 156 | + " p (physics - bots constantly move and jump around)\n" |
129 | " t (teleport - bots regularly teleport between regions on the grid)\n" + | 157 | + " g (grab - bots randomly click prims whether set clickable or not)\n" |
158 | + " n (none - bots do nothing)\n" | ||
159 | + " t (teleport - bots regularly teleport between regions on the grid)\n" | ||
130 | // " c (cross)" + | 160 | // " c (cross)" + |
131 | " -wear set appearance folder to load from (default: no)\n" + | 161 | + " -wear optional folder from which to load appearance data, \"no\" if there is no such folder (default: no)\n" |
132 | " -h, -help show this message"); | 162 | + " -h, -help show this message.\n"); |
133 | } | 163 | } |
134 | } | 164 | } |
135 | } | 165 | } |
diff --git a/bin/pCampbot.ini.example b/bin/pCampbot.ini.example new file mode 100644 index 0000000..f44feae --- /dev/null +++ b/bin/pCampbot.ini.example | |||
@@ -0,0 +1,15 @@ | |||
1 | ; This is the example config file for pCampbot | ||
2 | ; To use it, copy this file to pCampbot.ini and change settings if required | ||
3 | |||
4 | [Bot] | ||
5 | ; Control whether bots should regularly send agent updates | ||
6 | ; Not doing this will reduce CPU requirements for pCampbot but greatly | ||
7 | ; reduce the realism compared to viewers which are constantly sending AgentUpdates UDP packets. | ||
8 | ; Defaults to true. | ||
9 | SendAgentUpdates = true | ||
10 | |||
11 | ; Control whether bots will requests textures when receiving object information | ||
12 | ; Not doing this will reduce CPU requirements for pCampbot but greatly | ||
13 | ; reduce the realism compared to viewers which requests such texture data if not already cached. | ||
14 | ; Defaults to true. | ||
15 | RequestObjectTextures = true | ||