aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Framework/Console/ConsoleUtil.cs29
-rw-r--r--OpenSim/Framework/Monitoring/StatsLogger.cs2
-rw-r--r--OpenSim/Region/Application/ConfigurationLoader.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs24
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs42
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs34
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs11
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs220
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs46
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs4
-rw-r--r--OpenSim/Services/GridService/GridService.cs53
-rw-r--r--OpenSim/Services/HypergridService/GatekeeperService.cs12
-rw-r--r--OpenSim/Services/Interfaces/IGridService.cs5
-rw-r--r--OpenSim/Tools/pCampBot/Bot.cs142
-rw-r--r--OpenSim/Tools/pCampBot/BotManager.cs503
-rw-r--r--OpenSim/Tools/pCampBot/pCampBot.cs38
21 files changed, 938 insertions, 296 deletions
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs
index c0ff454..794bfaf 100644
--- a/OpenSim/Framework/Console/ConsoleUtil.cs
+++ b/OpenSim/Framework/Console/ConsoleUtil.cs
@@ -179,8 +179,8 @@ namespace OpenSim.Framework.Console
179 /// Convert a console integer to an int, automatically complaining if a console is given. 179 /// Convert a console integer to an int, automatically complaining if a console is given.
180 /// </summary> 180 /// </summary>
181 /// <param name='console'>Can be null if no console is available.</param> 181 /// <param name='console'>Can be null if no console is available.</param>
182 /// <param name='rawConsoleVector'>/param> 182 /// <param name='rawConsoleInt'>/param>
183 /// <param name='vector'></param> 183 /// <param name='i'></param>
184 /// <returns></returns> 184 /// <returns></returns>
185 public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i) 185 public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i)
186 { 186 {
@@ -194,6 +194,31 @@ namespace OpenSim.Framework.Console
194 194
195 return true; 195 return true;
196 } 196 }
197
198 /// <summary>
199 /// Convert a console integer to a natural int, automatically complaining if a console is given.
200 /// </summary>
201 /// <param name='console'>Can be null if no console is available.</param>
202 /// <param name='rawConsoleInt'>/param>
203 /// <param name='i'></param>
204 /// <returns></returns>
205 public static bool TryParseConsoleNaturalInt(ICommandConsole console, string rawConsoleInt, out int i)
206 {
207 if (TryParseConsoleInt(console, rawConsoleInt, out i))
208 {
209 if (i < 0)
210 {
211 if (console != null)
212 console.OutputFormat("ERROR: {0} is not a positive integer", rawConsoleInt);
213
214 return false;
215 }
216
217 return true;
218 }
219
220 return false;
221 }
197 222
198 /// <summary> 223 /// <summary>
199 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 224 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
diff --git a/OpenSim/Framework/Monitoring/StatsLogger.cs b/OpenSim/Framework/Monitoring/StatsLogger.cs
index fa2e1b6..1e4fa11 100644
--- a/OpenSim/Framework/Monitoring/StatsLogger.cs
+++ b/OpenSim/Framework/Monitoring/StatsLogger.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Framework.Monitoring
67 if (cmd[3] == "start") 67 if (cmd[3] == "start")
68 { 68 {
69 Start(); 69 Start();
70 con.OutputFormat("Now recording all stats very {0}ms to file", m_statsLogIntervalMs); 70 con.OutputFormat("Now recording all stats to file every {0}ms", m_statsLogIntervalMs);
71 } 71 }
72 else if (cmd[3] == "stop") 72 else if (cmd[3] == "stop")
73 { 73 {
diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs
index 3e93638..bc7ecb7 100644
--- a/OpenSim/Region/Application/ConfigurationLoader.cs
+++ b/OpenSim/Region/Application/ConfigurationLoader.cs
@@ -201,11 +201,11 @@ namespace OpenSim
201 201
202 envConfigSource.LoadEnv(); 202 envConfigSource.LoadEnv();
203 m_config.Source.Merge(envConfigSource); 203 m_config.Source.Merge(envConfigSource);
204 m_config.Source.ExpandKeyValues();
205 } 204 }
206 205
207
208 ReadConfigSettings(); 206 ReadConfigSettings();
207
208 m_config.Source.ExpandKeyValues();
209 209
210 return m_config; 210 return m_config;
211 } 211 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 8cbbfd9..dc28be8 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -6777,6 +6777,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6777 } 6777 }
6778 #endregion 6778 #endregion
6779 6779
6780 if (SceneAgent.IsChildAgent)
6781 {
6782 SendCantSitBecauseChildAgentResponse();
6783 return true;
6784 }
6785
6780 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; 6786 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
6781 6787
6782 if (handlerAgentRequestSit != null) 6788 if (handlerAgentRequestSit != null)
@@ -6801,6 +6807,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6801 } 6807 }
6802 #endregion 6808 #endregion
6803 6809
6810 if (SceneAgent.IsChildAgent)
6811 {
6812 SendCantSitBecauseChildAgentResponse();
6813 return true;
6814 }
6815
6804 AgentSit handlerAgentSit = OnAgentSit; 6816 AgentSit handlerAgentSit = OnAgentSit;
6805 if (handlerAgentSit != null) 6817 if (handlerAgentSit != null)
6806 { 6818 {
@@ -6810,6 +6822,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6810 return true; 6822 return true;
6811 } 6823 }
6812 6824
6825 /// <summary>
6826 /// Used when a child agent gets a sit response which should not be fulfilled.
6827 /// </summary>
6828 private void SendCantSitBecauseChildAgentResponse()
6829 {
6830 SendAlertMessage("Try moving closer. Can't sit on object because it is not in the same region as you.");
6831 }
6832
6813 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack) 6833 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack)
6814 { 6834 {
6815 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; 6835 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack;
@@ -12934,7 +12954,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12934 { 12954 {
12935 if (p is ScenePresence) 12955 if (p is ScenePresence)
12936 { 12956 {
12937 ScenePresence presence = p as ScenePresence;
12938 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities 12957 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities
12939 // There's no explicit message to send the client to tell it to stop flying.. it relies on the 12958 // There's no explicit message to send the client to tell it to stop flying.. it relies on the
12940 // velocity, collision plane and avatar height 12959 // velocity, collision plane and avatar height
@@ -12942,15 +12961,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12942 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air 12961 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air
12943 // when the avatar stands up 12962 // when the avatar stands up
12944 12963
12945 Vector3 pos = presence.AbsolutePosition;
12946
12947 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = 12964 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block =
12948 CreateImprovedTerseBlock(p, false); 12965 CreateImprovedTerseBlock(p, false);
12949 12966
12950 const float TIME_DILATION = 1.0f; 12967 const float TIME_DILATION = 1.0f;
12951 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 12968 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12952 12969
12953
12954 ImprovedTerseObjectUpdatePacket packet 12970 ImprovedTerseObjectUpdatePacket packet
12955 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( 12971 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12956 PacketType.ImprovedTerseObjectUpdate); 12972 PacketType.ImprovedTerseObjectUpdate);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index cef6177..ea660bd 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -538,7 +538,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
538 } 538 }
539 catch (Exception e) 539 catch (Exception e)
540 { 540 {
541 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message); 541 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e);
542 return null; 542 return null;
543 } 543 }
544 */ 544 */
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
index 966a05c..bf1cffb 100644
--- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -309,6 +309,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
309 string serverURI = string.Empty; 309 string serverURI = string.Empty;
310 GetUserProfileServerURI(targetID, out serverURI); 310 GetUserProfileServerURI(targetID, out serverURI);
311 UUID creatorId = UUID.Zero; 311 UUID creatorId = UUID.Zero;
312 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
312 313
313 OSDMap parameters= new OSDMap(); 314 OSDMap parameters= new OSDMap();
314 UUID.TryParse(args[0], out creatorId); 315 UUID.TryParse(args[0], out creatorId);
@@ -316,15 +317,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
316 OSD Params = (OSD)parameters; 317 OSD Params = (OSD)parameters;
317 if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString())) 318 if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
318 { 319 {
319 // Error Handling here! 320 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
320 // if(parameters.ContainsKey("message") 321 return;
321 } 322 }
322 323
323 parameters = (OSDMap)Params; 324 parameters = (OSDMap)Params;
324 325
325 OSDArray list = (OSDArray)parameters["result"]; 326 OSDArray list = (OSDArray)parameters["result"];
326 327
327 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
328 328
329 foreach(OSD map in list) 329 foreach(OSD map in list)
330 { 330 {
@@ -441,7 +441,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
441 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition; 441 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
442 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y); 442 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
443 ScenePresence p = FindPresence(remoteClient.AgentId); 443 ScenePresence p = FindPresence(remoteClient.AgentId);
444// Vector3 avaPos = p.AbsolutePosition;
445 444
446 string serverURI = string.Empty; 445 string serverURI = string.Empty;
447 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 446 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
@@ -542,14 +541,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
542 541
543 string serverURI = string.Empty; 542 string serverURI = string.Empty;
544 GetUserProfileServerURI(targetId, out serverURI); 543 GetUserProfileServerURI(targetId, out serverURI);
544
545 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
545 546
546 OSDMap parameters= new OSDMap(); 547 OSDMap parameters= new OSDMap();
547 parameters.Add("creatorId", OSD.FromUUID(targetId)); 548 parameters.Add("creatorId", OSD.FromUUID(targetId));
548 OSD Params = (OSD)parameters; 549 OSD Params = (OSD)parameters;
549 if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString())) 550 if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
550 { 551 {
551 remoteClient.SendAgentAlertMessage( 552 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
552 "Error requesting picks", false);
553 return; 553 return;
554 } 554 }
555 555
@@ -557,8 +557,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
557 557
558 OSDArray list = (OSDArray)parameters["result"]; 558 OSDArray list = (OSDArray)parameters["result"];
559 559
560 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
561
562 foreach(OSD map in list) 560 foreach(OSD map in list)
563 { 561 {
564 OSDMap m = (OSDMap)map; 562 OSDMap m = (OSDMap)map;
@@ -762,8 +760,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
762 object Note = (object)note; 760 object Note = (object)note;
763 if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString())) 761 if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
764 { 762 {
765 remoteClient.SendAgentAlertMessage( 763 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
766 "Error requesting note", false); 764 return;
767 } 765 }
768 note = (UserProfileNotes) Note; 766 note = (UserProfileNotes) Note;
769 767
@@ -796,8 +794,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
796 object Note = note; 794 object Note = note;
797 if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString())) 795 if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
798 { 796 {
799 remoteClient.SendAgentAlertMessage( 797 return;
800 "Error updating note", false);
801 } 798 }
802 } 799 }
803 #endregion Notes 800 #endregion Notes
@@ -1033,8 +1030,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
1033 OSD Params = (OSD)parameters; 1030 OSD Params = (OSD)parameters;
1034 if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString())) 1031 if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
1035 { 1032 {
1036 // Error Handling here!
1037 // if(parameters.ContainsKey("message")
1038 return false; 1033 return false;
1039 } 1034 }
1040 1035
@@ -1224,7 +1219,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
1224 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData); 1219 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1225 1220
1226 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri); 1221 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1227 // webRequest.Credentials = new NetworkCredential(rpcUser, rpcPass); 1222
1228 webRequest.ContentType = "application/json-rpc"; 1223 webRequest.ContentType = "application/json-rpc";
1229 webRequest.Method = "POST"; 1224 webRequest.Method = "POST";
1230 1225
@@ -1245,7 +1240,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
1245 } 1240 }
1246 1241
1247 Stream rstream = webResponse.GetResponseStream(); 1242 Stream rstream = webResponse.GetResponseStream();
1248 OSDMap mret = (OSDMap)OSDParser.DeserializeJson(rstream); 1243 if (rstream.Length < 1)
1244 return false;
1245
1246 OSDMap mret = new OSDMap();
1247 try
1248 {
1249 mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1250 }
1251 catch (Exception e)
1252 {
1253 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1254 return false;
1255 }
1256
1249 1257
1250 if (mret.ContainsKey("error")) 1258 if (mret.ContainsKey("error"))
1251 return false; 1259 return false;
@@ -1310,6 +1318,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
1310 } 1318 }
1311 1319
1312 Stream rstream = webResponse.GetResponseStream(); 1320 Stream rstream = webResponse.GetResponseStream();
1321 if (rstream.Length < 1)
1322 return false;
1313 1323
1314 OSDMap response = new OSDMap(); 1324 OSDMap response = new OSDMap();
1315 try 1325 try
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 6ff9988..1f3e7a1 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -837,8 +837,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
837 } 837 }
838 838
839 m_log.WarnFormat( 839 m_log.WarnFormat(
840 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", 840 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
841 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 841 sp.Name, finalDestination.RegionName, sp.Scene.Name);
842 842
843 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); 843 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
844 return; 844 return;
@@ -1058,8 +1058,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1058 } 1058 }
1059 1059
1060 m_log.WarnFormat( 1060 m_log.WarnFormat(
1061 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", 1061 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
1062 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 1062 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1063 1063
1064 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); 1064 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
1065 return; 1065 return;
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 9c441ed..0c74b49 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -48,8 +48,8 @@ namespace OpenSim.Region.CoreModules.World.Region
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")]
49 public class RestartModule : INonSharedRegionModule, IRestartModule 49 public class RestartModule : INonSharedRegionModule, IRestartModule
50 { 50 {
51// private static readonly ILog m_log = 51 private static readonly ILog m_log =
52// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 protected Scene m_Scene; 54 protected Scene m_Scene;
55 protected Timer m_CountdownTimer = null; 55 protected Timer m_CountdownTimer = null;
@@ -223,11 +223,25 @@ namespace OpenSim.Region.CoreModules.World.Region
223 223
224 public void SetTimer(int intervalSeconds) 224 public void SetTimer(int intervalSeconds)
225 { 225 {
226 m_CountdownTimer = new Timer(); 226 if (intervalSeconds > 0)
227 m_CountdownTimer.AutoReset = false; 227 {
228 m_CountdownTimer.Interval = intervalSeconds * 1000; 228 m_CountdownTimer = new Timer();
229 m_CountdownTimer.Elapsed += OnTimer; 229 m_CountdownTimer.AutoReset = false;
230 m_CountdownTimer.Start(); 230 m_CountdownTimer.Interval = intervalSeconds * 1000;
231 m_CountdownTimer.Elapsed += OnTimer;
232 m_CountdownTimer.Start();
233 }
234 else if (m_CountdownTimer != null)
235 {
236 m_CountdownTimer.Stop();
237 m_CountdownTimer = null;
238 }
239 else
240 {
241 m_log.WarnFormat(
242 "[RESTART MODULE]: Tried to set restart timer to {0} in {1}, which is not a valid interval",
243 intervalSeconds, m_Scene.Name);
244 }
231 } 245 }
232 246
233 private void OnTimer(object source, ElapsedEventArgs e) 247 private void OnTimer(object source, ElapsedEventArgs e)
@@ -332,4 +346,4 @@ namespace OpenSim.Region.CoreModules.World.Region
332 } 346 }
333 } 347 }
334 } 348 }
335} \ No newline at end of file 349}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 56bdc63..f864392 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3986,7 +3986,7 @@ namespace OpenSim.Region.Framework.Scenes
3986 3986
3987 try 3987 try
3988 { 3988 {
3989 if (!AuthorizeUser(acd, SeeIntoRegion, out reason)) 3989 if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
3990 { 3990 {
3991 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 3991 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3992 return false; 3992 return false;
@@ -4596,10 +4596,27 @@ namespace OpenSim.Region.Framework.Scenes
4596 4596
4597 // Check that the auth_token is valid 4597 // Check that the auth_token is valid
4598 AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID); 4598 AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID);
4599 if (acd != null && acd.SessionID.ToString() == auth_token) 4599
4600 if (acd == null)
4601 {
4602 m_log.DebugFormat(
4603 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4604 agentID, Name);
4605
4606 return false;
4607 }
4608
4609 if (acd.SessionID.ToString() == auth_token)
4610 {
4600 return IncomingCloseAgent(agentID, force); 4611 return IncomingCloseAgent(agentID, force);
4612 }
4601 else 4613 else
4602 m_log.ErrorFormat("[SCENE]: Request to close agent {0} with invalid authorization token {1}", agentID, auth_token); 4614 {
4615 m_log.WarnFormat(
4616 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4617 agentID, auth_token, Name);
4618 }
4619
4603 return false; 4620 return false;
4604 } 4621 }
4605 4622
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e599e90..b0f8991 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -631,40 +631,16 @@ namespace OpenSim.Region.Framework.Scenes
631 protected internal ScenePresence CreateAndAddChildScenePresence( 631 protected internal ScenePresence CreateAndAddChildScenePresence(
632 IClientAPI client, AvatarAppearance appearance, PresenceType type) 632 IClientAPI client, AvatarAppearance appearance, PresenceType type)
633 { 633 {
634 ScenePresence newAvatar = null;
635
636 // ScenePresence always defaults to child agent 634 // ScenePresence always defaults to child agent
637 newAvatar = new ScenePresence(client, m_parentScene, appearance, type); 635 ScenePresence presence = new ScenePresence(client, m_parentScene, appearance, type);
638
639 AddScenePresence(newAvatar);
640
641 return newAvatar;
642 }
643
644 /// <summary>
645 /// Add a presence to the scene
646 /// </summary>
647 /// <param name="presence"></param>
648 protected internal void AddScenePresence(ScenePresence presence)
649 {
650 // Always a child when added to the scene
651 bool child = presence.IsChildAgent;
652
653 if (child)
654 {
655 m_numChildAgents++;
656 }
657 else
658 {
659 m_numRootAgents++;
660 presence.AddToPhysicalScene(false);
661 }
662 636
663 Entities[presence.UUID] = presence; 637 Entities[presence.UUID] = presence;
664 638
665 m_scenePresencesLock.EnterWriteLock(); 639 m_scenePresencesLock.EnterWriteLock();
666 try 640 try
667 { 641 {
642 m_numChildAgents++;
643
668 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 644 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
669 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 645 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
670 646
@@ -675,7 +651,7 @@ namespace OpenSim.Region.Framework.Scenes
675 } 651 }
676 else 652 else
677 { 653 {
678 // Remember the old presene reference from the dictionary 654 // Remember the old presence reference from the dictionary
679 ScenePresence oldref = newmap[presence.UUID]; 655 ScenePresence oldref = newmap[presence.UUID];
680 // Replace the presence reference in the dictionary with the new value 656 // Replace the presence reference in the dictionary with the new value
681 newmap[presence.UUID] = presence; 657 newmap[presence.UUID] = presence;
@@ -691,6 +667,8 @@ namespace OpenSim.Region.Framework.Scenes
691 { 667 {
692 m_scenePresencesLock.ExitWriteLock(); 668 m_scenePresencesLock.ExitWriteLock();
693 } 669 }
670
671 return presence;
694 } 672 }
695 673
696 /// <summary> 674 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 59a453a..cf03d7c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -4522,7 +4522,7 @@ namespace OpenSim.Region.Framework.Scenes
4522 // For now, we use the NINJA naming scheme for identifying joints. 4522 // For now, we use the NINJA naming scheme for identifying joints.
4523 // In the future, we can support other joint specification schemes such as a 4523 // In the future, we can support other joint specification schemes such as a
4524 // custom checkbox in the viewer GUI. 4524 // custom checkbox in the viewer GUI.
4525 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4525 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4526 { 4526 {
4527 return IsHingeJoint() || IsBallJoint(); 4527 return IsHingeJoint() || IsBallJoint();
4528 } 4528 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 3f4979e..88ecda2 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2707,6 +2707,9 @@ namespace OpenSim.Region.Framework.Scenes
2707 2707
2708 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 2708 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2709 { 2709 {
2710 if (IsChildAgent)
2711 return;
2712
2710 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2713 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2711 2714
2712 if (part != null) 2715 if (part != null)
@@ -2793,6 +2796,9 @@ namespace OpenSim.Region.Framework.Scenes
2793 2796
2794 public void HandleAgentSitOnGround() 2797 public void HandleAgentSitOnGround()
2795 { 2798 {
2799 if (IsChildAgent)
2800 return;
2801
2796// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 2802// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
2797 m_AngularVelocity = Vector3.Zero; 2803 m_AngularVelocity = Vector3.Zero;
2798 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 2804 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
@@ -3451,11 +3457,6 @@ namespace OpenSim.Region.Framework.Scenes
3451 } 3457 }
3452 } 3458 }
3453 3459
3454 public void RestoreInCurrentScene()
3455 {
3456 AddToPhysicalScene(false); // not exactly false
3457 }
3458
3459 public void Reset() 3460 public void Reset()
3460 { 3461 {
3461// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); 3462// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs
new file mode 100644
index 0000000..5a6b284
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs
@@ -0,0 +1,220 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Text;
33using System.Text.RegularExpressions;
34using log4net;
35using Mono.Addins;
36using NDesk.Options;
37using Nini.Config;
38using OpenMetaverse;
39using OpenSim.Framework;
40using OpenSim.Framework.Console;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.OptionalModules.Avatar.SitStand
45{
46 /// <summary>
47 /// A module that just holds commands for changing avatar sitting and standing states.
48 /// </summary>
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AnimationsCommandModule")]
50 public class SitStandCommandModule : INonSharedRegionModule
51 {
52// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private Scene m_scene;
55
56 public string Name { get { return "SitStand Command Module"; } }
57
58 public Type ReplaceableInterface { get { return null; } }
59
60 public void Initialise(IConfigSource source)
61 {
62// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: INITIALIZED MODULE");
63 }
64
65 public void PostInitialise()
66 {
67// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: POST INITIALIZED MODULE");
68 }
69
70 public void Close()
71 {
72// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: CLOSED MODULE");
73 }
74
75 public void AddRegion(Scene scene)
76 {
77// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
78 }
79
80 public void RemoveRegion(Scene scene)
81 {
82// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
83 }
84
85 public void RegionLoaded(Scene scene)
86 {
87// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
88
89 m_scene = scene;
90
91 scene.AddCommand(
92 "Users", this, "sit user name",
93 "sit user name [--regex] <first-name> <last-name>",
94 "Sit the named user on an unoccupied object with a sit target.",
95 "If there are no such objects then nothing happens.\n"
96 + "If --regex is specified then the names are treated as regular expressions.",
97 HandleSitUserNameCommand);
98
99 scene.AddCommand(
100 "Users", this, "stand user name",
101 "stand user name [--regex] <first-name> <last-name>",
102 "Stand the named user.",
103 "If --regex is specified then the names are treated as regular expressions.",
104 HandleStandUserNameCommand);
105 }
106
107 private void HandleSitUserNameCommand(string module, string[] cmd)
108 {
109 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
110 return;
111
112 if (cmd.Length < 5)
113 {
114 MainConsole.Instance.Output("Usage: sit user name [--regex] <first-name> <last-name>");
115 return;
116 }
117
118 List<ScenePresence> scenePresences = GetScenePresences(cmd);
119
120 foreach (ScenePresence sp in scenePresences)
121 {
122 if (sp.SitGround || sp.IsSatOnObject)
123 continue;
124
125 SceneObjectPart sitPart = null;
126 List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups();
127
128 foreach (SceneObjectGroup sceneObject in sceneObjects)
129 {
130 if (sceneObject.IsAttachment)
131 continue;
132
133 foreach (SceneObjectPart part in sceneObject.Parts)
134 {
135 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
136 {
137 sitPart = part;
138 break;
139 }
140 }
141 }
142
143 if (sitPart != null)
144 {
145 MainConsole.Instance.OutputFormat(
146 "Sitting {0} on {1} {2} in {3}",
147 sp.Name, sitPart.ParentGroup.Name, sitPart.ParentGroup.UUID, m_scene.Name);
148
149 sp.HandleAgentRequestSit(sp.ControllingClient, sp.UUID, sitPart.UUID, Vector3.Zero);
150 sp.HandleAgentSit(sp.ControllingClient, sp.UUID);
151 }
152 else
153 {
154 MainConsole.Instance.OutputFormat(
155 "Could not find any unoccupied set seat on which to sit {0} in {1}. Aborting",
156 sp.Name, m_scene.Name);
157
158 break;
159 }
160 }
161 }
162
163 private void HandleStandUserNameCommand(string module, string[] cmd)
164 {
165 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
166 return;
167
168 if (cmd.Length < 5)
169 {
170 MainConsole.Instance.Output("Usage: stand user name [--regex] <first-name> <last-name>");
171 return;
172 }
173
174 List<ScenePresence> scenePresences = GetScenePresences(cmd);
175
176 foreach (ScenePresence sp in scenePresences)
177 {
178 if (sp.SitGround || sp.IsSatOnObject)
179 {
180 MainConsole.Instance.OutputFormat("Standing {0} in {1}", sp.Name, m_scene.Name);
181 sp.StandUp();
182 }
183 }
184 }
185
186 private List<ScenePresence> GetScenePresences(string[] cmdParams)
187 {
188 bool useRegex = false;
189 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
190
191 List<string> mainParams = options.Parse(cmdParams);
192
193 string firstName = mainParams[3];
194 string lastName = mainParams[4];
195
196 List<ScenePresence> scenePresencesMatched = new List<ScenePresence>();
197
198 if (useRegex)
199 {
200 Regex nameRegex = new Regex(string.Format("{0} {1}", firstName, lastName));
201 List<ScenePresence> scenePresences = m_scene.GetScenePresences();
202
203 foreach (ScenePresence sp in scenePresences)
204 {
205 if (!sp.IsChildAgent && nameRegex.IsMatch(sp.Name))
206 scenePresencesMatched.Add(sp);
207 }
208 }
209 else
210 {
211 ScenePresence sp = m_scene.GetScenePresence(firstName, lastName);
212
213 if (sp != null && !sp.IsChildAgent)
214 scenePresencesMatched.Add(sp);
215 }
216
217 return scenePresencesMatched;
218 }
219 }
220} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index 6db5f5e..2a820be 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -1221,6 +1221,50 @@ private sealed class BulletConstraintXNA : BulletConstraint
1221 //BSParam.TerrainImplementation = 0; 1221 //BSParam.TerrainImplementation = 0;
1222 world.SetGravity(new IndexedVector3(0,0,p.gravity)); 1222 world.SetGravity(new IndexedVector3(0,0,p.gravity));
1223 1223
1224 // Turn off Pooling since globals and pooling are bad for threading.
1225 BulletGlobals.VoronoiSimplexSolverPool.SetPoolingEnabled(false);
1226 BulletGlobals.SubSimplexConvexCastPool.SetPoolingEnabled(false);
1227 BulletGlobals.ManifoldPointPool.SetPoolingEnabled(false);
1228 BulletGlobals.CastResultPool.SetPoolingEnabled(false);
1229 BulletGlobals.SphereShapePool.SetPoolingEnabled(false);
1230 BulletGlobals.DbvtNodePool.SetPoolingEnabled(false);
1231 BulletGlobals.SingleRayCallbackPool.SetPoolingEnabled(false);
1232 BulletGlobals.SubSimplexClosestResultPool.SetPoolingEnabled(false);
1233 BulletGlobals.GjkPairDetectorPool.SetPoolingEnabled(false);
1234 BulletGlobals.DbvtTreeColliderPool.SetPoolingEnabled(false);
1235 BulletGlobals.SingleSweepCallbackPool.SetPoolingEnabled(false);
1236 BulletGlobals.BroadphaseRayTesterPool.SetPoolingEnabled(false);
1237 BulletGlobals.ClosestNotMeConvexResultCallbackPool.SetPoolingEnabled(false);
1238 BulletGlobals.GjkEpaPenetrationDepthSolverPool.SetPoolingEnabled(false);
1239 BulletGlobals.ContinuousConvexCollisionPool.SetPoolingEnabled(false);
1240 BulletGlobals.DbvtStackDataBlockPool.SetPoolingEnabled(false);
1241
1242 BulletGlobals.BoxBoxCollisionAlgorithmPool.SetPoolingEnabled(false);
1243 BulletGlobals.CompoundCollisionAlgorithmPool.SetPoolingEnabled(false);
1244 BulletGlobals.ConvexConcaveCollisionAlgorithmPool.SetPoolingEnabled(false);
1245 BulletGlobals.ConvexConvexAlgorithmPool.SetPoolingEnabled(false);
1246 BulletGlobals.ConvexPlaneAlgorithmPool.SetPoolingEnabled(false);
1247 BulletGlobals.SphereBoxCollisionAlgorithmPool.SetPoolingEnabled(false);
1248 BulletGlobals.SphereSphereCollisionAlgorithmPool.SetPoolingEnabled(false);
1249 BulletGlobals.SphereTriangleCollisionAlgorithmPool.SetPoolingEnabled(false);
1250 BulletGlobals.GImpactCollisionAlgorithmPool.SetPoolingEnabled(false);
1251 BulletGlobals.GjkEpaSolver2MinkowskiDiffPool.SetPoolingEnabled(false);
1252 BulletGlobals.PersistentManifoldPool.SetPoolingEnabled(false);
1253 BulletGlobals.ManifoldResultPool.SetPoolingEnabled(false);
1254 BulletGlobals.GJKPool.SetPoolingEnabled(false);
1255 BulletGlobals.GIM_ShapeRetrieverPool.SetPoolingEnabled(false);
1256 BulletGlobals.TriangleShapePool.SetPoolingEnabled(false);
1257 BulletGlobals.SphereTriangleDetectorPool.SetPoolingEnabled(false);
1258 BulletGlobals.CompoundLeafCallbackPool.SetPoolingEnabled(false);
1259 BulletGlobals.GjkConvexCastPool.SetPoolingEnabled(false);
1260 BulletGlobals.LocalTriangleSphereCastCallbackPool.SetPoolingEnabled(false);
1261 BulletGlobals.BridgeTriangleRaycastCallbackPool.SetPoolingEnabled(false);
1262 BulletGlobals.BridgeTriangleConcaveRaycastCallbackPool.SetPoolingEnabled(false);
1263 BulletGlobals.BridgeTriangleConvexcastCallbackPool.SetPoolingEnabled(false);
1264 BulletGlobals.MyNodeOverlapCallbackPool.SetPoolingEnabled(false);
1265 BulletGlobals.ClosestRayResultCallbackPool.SetPoolingEnabled(false);
1266 BulletGlobals.DebugDrawcallbackPool.SetPoolingEnabled(false);
1267
1224 return world; 1268 return world;
1225 } 1269 }
1226 //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL 1270 //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL
@@ -1914,7 +1958,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1914 heightMap, scaleFactor, 1958 heightMap, scaleFactor,
1915 minHeight, maxHeight, upAxis, 1959 minHeight, maxHeight, upAxis,
1916 false); 1960 false);
1917 terrainShape.SetMargin(collisionMargin + 0.5f); 1961 terrainShape.SetMargin(collisionMargin);
1918 terrainShape.SetUseDiamondSubdivision(true); 1962 terrainShape.SetUseDiamondSubdivision(true);
1919 terrainShape.SetUserPointer(id); 1963 terrainShape.SetUserPointer(id);
1920 return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN); 1964 return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 88d50b4..c92c9b9 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -946,7 +946,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
946 946
947 private void ProcessRegularTaints() 947 private void ProcessRegularTaints()
948 { 948 {
949 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process 949 if (m_initialized && _taintOperations.Count > 0) // save allocating new list if there is nothing to process
950 { 950 {
951 // swizzle a new list into the list location so we can process what's there 951 // swizzle a new list into the list location so we can process what's there
952 List<TaintCallbackEntry> oldList; 952 List<TaintCallbackEntry> oldList;
@@ -989,7 +989,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
989 // Taints that happen after the normal taint processing but before the simulation step. 989 // Taints that happen after the normal taint processing but before the simulation step.
990 private void ProcessPostTaintTaints() 990 private void ProcessPostTaintTaints()
991 { 991 {
992 if (_postTaintOperations.Count > 0) 992 if (m_initialized && _postTaintOperations.Count > 0)
993 { 993 {
994 Dictionary<string, TaintCallbackEntry> oldList; 994 Dictionary<string, TaintCallbackEntry> oldList;
995 lock (_taintLock) 995 lock (_taintLock)
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index daebf8b..a1485c8 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -86,7 +86,7 @@ namespace OpenSim.Services.GridService
86 { 86 {
87 MainConsole.Instance.Commands.AddCommand("Regions", true, 87 MainConsole.Instance.Commands.AddCommand("Regions", true,
88 "deregister region id", 88 "deregister region id",
89 "deregister region id <Region UUID>", 89 "deregister region id <region-id>+",
90 "Deregister a region manually.", 90 "Deregister a region manually.",
91 String.Empty, 91 String.Empty,
92 HandleDeregisterRegion); 92 HandleDeregisterRegion);
@@ -526,40 +526,41 @@ namespace OpenSim.Services.GridService
526 526
527 private void HandleDeregisterRegion(string module, string[] cmd) 527 private void HandleDeregisterRegion(string module, string[] cmd)
528 { 528 {
529 if (cmd.Length != 4) 529 if (cmd.Length < 4)
530 { 530 {
531 MainConsole.Instance.Output("Syntax: degregister region id <Region UUID>"); 531 MainConsole.Instance.Output("Usage: degregister region id <region-id>+");
532 return; 532 return;
533 } 533 }
534 534
535 string rawRegionUuid = cmd[3]; 535 for (int i = 3; i < cmd.Length; i++)
536 UUID regionUuid;
537
538 if (!UUID.TryParse(rawRegionUuid, out regionUuid))
539 { 536 {
540 MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid); 537 string rawRegionUuid = cmd[i];
541 return; 538 UUID regionUuid;
542 }
543 539
544 GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid); 540 if (!UUID.TryParse(rawRegionUuid, out regionUuid))
541 {
542 MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid);
543 return;
544 }
545 545
546 if (region == null) 546 GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid);
547 {
548 MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid);
549 return;
550 }
551 547
552 if (DeregisterRegion(regionUuid)) 548 if (region == null)
553 { 549 {
554 MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid); 550 MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid);
555 } 551 return;
556 else 552 }
557 {
558 // I don't think this can ever occur if we know that the region exists.
559 MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid);
560 }
561 553
562 return; 554 if (DeregisterRegion(regionUuid))
555 {
556 MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid);
557 }
558 else
559 {
560 // I don't think this can ever occur if we know that the region exists.
561 MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid);
562 }
563 }
563 } 564 }
564 565
565 private void HandleShowRegions(string module, string[] cmd) 566 private void HandleShowRegions(string module, string[] cmd)
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs
index 0a3e70b..e10c4cb 100644
--- a/OpenSim/Services/HypergridService/GatekeeperService.cs
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -326,7 +326,7 @@ namespace OpenSim.Services.HypergridService
326 return false; 326 return false;
327 } 327 }
328 328
329 m_log.DebugFormat("[GATEKEEPER SERVICE]: User is OK"); 329 m_log.DebugFormat("[GATEKEEPER SERVICE]: User {0} is ok", aCircuit.Name);
330 330
331 bool isFirstLogin = false; 331 bool isFirstLogin = false;
332 // 332 //
@@ -345,7 +345,8 @@ namespace OpenSim.Services.HypergridService
345 aCircuit.firstname, aCircuit.lastname); 345 aCircuit.firstname, aCircuit.lastname);
346 return false; 346 return false;
347 } 347 }
348 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok"); 348
349 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence {0} is ok", aCircuit.Name);
349 350
350 // Also login foreigners with GridUser service 351 // Also login foreigners with GridUser service
351 if (m_GridUserService != null && account == null) 352 if (m_GridUserService != null && account == null)
@@ -376,7 +377,9 @@ namespace OpenSim.Services.HypergridService
376 reason = "Destination region not found"; 377 reason = "Destination region not found";
377 return false; 378 return false;
378 } 379 }
379 m_log.DebugFormat("[GATEKEEPER SERVICE]: destination ok: {0}", destination.RegionName); 380
381 m_log.DebugFormat(
382 "[GATEKEEPER SERVICE]: Destination {0} is ok for {1}", destination.RegionName, aCircuit.Name);
380 383
381 // 384 //
382 // Adjust the visible name 385 // Adjust the visible name
@@ -410,7 +413,8 @@ namespace OpenSim.Services.HypergridService
410 // Preserve our TeleportFlags we have gathered so-far 413 // Preserve our TeleportFlags we have gathered so-far
411 loginFlag |= (Constants.TeleportFlags) aCircuit.teleportFlags; 414 loginFlag |= (Constants.TeleportFlags) aCircuit.teleportFlags;
412 415
413 m_log.DebugFormat("[GATEKEEPER SERVICE]: launching agent {0}", loginFlag); 416 m_log.DebugFormat("[GATEKEEPER SERVICE]: Launching {0} {1}", aCircuit.Name, loginFlag);
417
414 return m_SimulationService.CreateAgent(destination, aCircuit, (uint)loginFlag, out reason); 418 return m_SimulationService.CreateAgent(destination, aCircuit, (uint)loginFlag, out reason);
415 } 419 }
416 420
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs
index 3f4c958..cecbe9e 100644
--- a/OpenSim/Services/Interfaces/IGridService.cs
+++ b/OpenSim/Services/Interfaces/IGridService.cs
@@ -137,7 +137,10 @@ namespace OpenSim.Services.Interfaces
137 if ( m_serverURI != string.Empty ) { 137 if ( m_serverURI != string.Empty ) {
138 return m_serverURI; 138 return m_serverURI;
139 } else { 139 } else {
140 return "http://" + m_externalHostName + ":" + m_httpPort + "/"; 140 if (m_httpPort == 0)
141 return "http://" + m_externalHostName + "/";
142 else
143 return "http://" + m_externalHostName + ":" + m_httpPort + "/";
141 } 144 }
142 } 145 }
143 set { 146 set {
diff --git a/OpenSim/Tools/pCampBot/Bot.cs b/OpenSim/Tools/pCampBot/Bot.cs
index 32bf32b..d418288 100644
--- a/OpenSim/Tools/pCampBot/Bot.cs
+++ b/OpenSim/Tools/pCampBot/Bot.cs
@@ -97,6 +97,28 @@ namespace pCampBot
97 /// </summary> 97 /// </summary>
98 public ConnectionState ConnectionState { get; private set; } 98 public ConnectionState ConnectionState { get; private set; }
99 99
100 public List<Simulator> Simulators
101 {
102 get
103 {
104 lock (Client.Network.Simulators)
105 return new List<Simulator>(Client.Network.Simulators);
106 }
107 }
108
109 /// <summary>
110 /// The number of connections that this bot has to different simulators.
111 /// </summary>
112 /// <value>Includes both root and child connections.</value>
113 public int SimulatorsCount
114 {
115 get
116 {
117 lock (Client.Network.Simulators)
118 return Client.Network.Simulators.Count;
119 }
120 }
121
100 public string FirstName { get; private set; } 122 public string FirstName { get; private set; }
101 public string LastName { get; private set; } 123 public string LastName { get; private set; }
102 public string Name { get; private set; } 124 public string Name { get; private set; }
@@ -144,8 +166,6 @@ namespace pCampBot
144 ConnectionState = ConnectionState.Disconnected; 166 ConnectionState = ConnectionState.Disconnected;
145 167
146 behaviours.ForEach(b => b.Initialize(this)); 168 behaviours.ForEach(b => b.Initialize(this));
147
148 Client = new GridClient();
149 169
150 Random = new Random(Environment.TickCount);// We do stuff randomly here 170 Random = new Random(Environment.TickCount);// We do stuff randomly here
151 FirstName = firstName; 171 FirstName = firstName;
@@ -157,6 +177,59 @@ namespace pCampBot
157 177
158 Manager = bm; 178 Manager = bm;
159 Behaviours = behaviours; 179 Behaviours = behaviours;
180
181 // Only calling for use as a template.
182 CreateLibOmvClient();
183 }
184
185 private void CreateLibOmvClient()
186 {
187 GridClient newClient = new GridClient();
188
189 if (Client != null)
190 {
191 newClient.Settings.LOGIN_SERVER = Client.Settings.LOGIN_SERVER;
192 newClient.Settings.ALWAYS_DECODE_OBJECTS = Client.Settings.ALWAYS_DECODE_OBJECTS;
193 newClient.Settings.AVATAR_TRACKING = Client.Settings.AVATAR_TRACKING;
194 newClient.Settings.OBJECT_TRACKING = Client.Settings.OBJECT_TRACKING;
195 newClient.Settings.SEND_AGENT_THROTTLE = Client.Settings.SEND_AGENT_THROTTLE;
196 newClient.Settings.SEND_AGENT_UPDATES = Client.Settings.SEND_AGENT_UPDATES;
197 newClient.Settings.SEND_PINGS = Client.Settings.SEND_PINGS;
198 newClient.Settings.STORE_LAND_PATCHES = Client.Settings.STORE_LAND_PATCHES;
199 newClient.Settings.USE_ASSET_CACHE = Client.Settings.USE_ASSET_CACHE;
200 newClient.Settings.MULTIPLE_SIMS = Client.Settings.MULTIPLE_SIMS;
201 newClient.Throttle.Asset = Client.Throttle.Asset;
202 newClient.Throttle.Land = Client.Throttle.Land;
203 newClient.Throttle.Task = Client.Throttle.Task;
204 newClient.Throttle.Texture = Client.Throttle.Texture;
205 newClient.Throttle.Wind = Client.Throttle.Wind;
206 newClient.Throttle.Total = Client.Throttle.Total;
207 }
208 else
209 {
210 newClient.Settings.LOGIN_SERVER = LoginUri;
211 newClient.Settings.ALWAYS_DECODE_OBJECTS = false;
212 newClient.Settings.AVATAR_TRACKING = false;
213 newClient.Settings.OBJECT_TRACKING = false;
214 newClient.Settings.SEND_AGENT_THROTTLE = true;
215 newClient.Settings.SEND_PINGS = true;
216 newClient.Settings.STORE_LAND_PATCHES = false;
217 newClient.Settings.USE_ASSET_CACHE = false;
218 newClient.Settings.MULTIPLE_SIMS = true;
219 newClient.Throttle.Asset = 100000;
220 newClient.Throttle.Land = 100000;
221 newClient.Throttle.Task = 100000;
222 newClient.Throttle.Texture = 100000;
223 newClient.Throttle.Wind = 100000;
224 newClient.Throttle.Total = 400000;
225 }
226
227 newClient.Network.LoginProgress += this.Network_LoginProgress;
228 newClient.Network.SimConnected += this.Network_SimConnected;
229 newClient.Network.Disconnected += this.Network_OnDisconnected;
230 newClient.Objects.ObjectUpdate += Objects_NewPrim;
231
232 Client = newClient;
160 } 233 }
161 234
162 //We do our actions here. This is where one would 235 //We do our actions here. This is where one would
@@ -179,7 +252,7 @@ namespace pCampBot
179 /// <summary> 252 /// <summary>
180 /// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes. 253 /// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes.
181 /// </summary> 254 /// </summary>
182 public void shutdown() 255 public void Disconnect()
183 { 256 {
184 ConnectionState = ConnectionState.Disconnecting; 257 ConnectionState = ConnectionState.Disconnecting;
185 258
@@ -189,34 +262,27 @@ namespace pCampBot
189 Client.Network.Logout(); 262 Client.Network.Logout();
190 } 263 }
191 264
265 public void Connect()
266 {
267 Thread connectThread = new Thread(ConnectInternal);
268 connectThread.Name = Name;
269 connectThread.IsBackground = true;
270
271 connectThread.Start();
272 }
273
192 /// <summary> 274 /// <summary>
193 /// This is the bot startup loop. 275 /// This is the bot startup loop.
194 /// </summary> 276 /// </summary>
195 public void startup() 277 private void ConnectInternal()
196 { 278 {
197 Client.Settings.LOGIN_SERVER = LoginUri;
198 Client.Settings.ALWAYS_DECODE_OBJECTS = false;
199 Client.Settings.AVATAR_TRACKING = false;
200 Client.Settings.OBJECT_TRACKING = false;
201 Client.Settings.SEND_AGENT_THROTTLE = true;
202 Client.Settings.SEND_AGENT_UPDATES = false;
203 Client.Settings.SEND_PINGS = true;
204 Client.Settings.STORE_LAND_PATCHES = false;
205 Client.Settings.USE_ASSET_CACHE = false;
206 Client.Settings.MULTIPLE_SIMS = true;
207 Client.Throttle.Asset = 100000;
208 Client.Throttle.Land = 100000;
209 Client.Throttle.Task = 100000;
210 Client.Throttle.Texture = 100000;
211 Client.Throttle.Wind = 100000;
212 Client.Throttle.Total = 400000;
213 Client.Network.LoginProgress += this.Network_LoginProgress;
214 Client.Network.SimConnected += this.Network_SimConnected;
215 Client.Network.Disconnected += this.Network_OnDisconnected;
216 Client.Objects.ObjectUpdate += Objects_NewPrim;
217
218 ConnectionState = ConnectionState.Connecting; 279 ConnectionState = ConnectionState.Connecting;
219 280
281 // Current create a new client on each connect. libomv doesn't seem to process new sim
282 // information (e.g. EstablishAgentCommunication events) if connecting after a disceonnect with the same
283 // client
284 CreateLibOmvClient();
285
220 if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", StartLocation, "Your name")) 286 if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", StartLocation, "Your name"))
221 { 287 {
222 ConnectionState = ConnectionState.Connected; 288 ConnectionState = ConnectionState.Connected;
@@ -261,6 +327,30 @@ namespace pCampBot
261 } 327 }
262 } 328 }
263 329
330 /// <summary>
331 /// Sit this bot on the ground.
332 /// </summary>
333 public void SitOnGround()
334 {
335 if (ConnectionState == ConnectionState.Connected)
336 Client.Self.SitOnGround();
337 }
338
339 /// <summary>
340 /// Stand this bot
341 /// </summary>
342 public void Stand()
343 {
344 if (ConnectionState == ConnectionState.Connected)
345 {
346 // Unlike sit on ground, here libomv checks whether we have SEND_AGENT_UPDATES enabled.
347 bool prevUpdatesSetting = Client.Settings.SEND_AGENT_UPDATES;
348 Client.Settings.SEND_AGENT_UPDATES = true;
349 Client.Self.Stand();
350 Client.Settings.SEND_AGENT_UPDATES = prevUpdatesSetting;
351 }
352 }
353
264 public void SaveDefaultAppearance() 354 public void SaveDefaultAppearance()
265 { 355 {
266 saveDir = "MyAppearance/" + FirstName + "_" + LastName; 356 saveDir = "MyAppearance/" + FirstName + "_" + LastName;
@@ -461,6 +551,8 @@ namespace pCampBot
461// || args.Reason == NetworkManager.DisconnectType.NetworkTimeout) 551// || args.Reason == NetworkManager.DisconnectType.NetworkTimeout)
462// && OnDisconnected != null) 552// && OnDisconnected != null)
463 553
554
555
464 if ( 556 if (
465 (args.Reason == NetworkManager.DisconnectType.ClientInitiated 557 (args.Reason == NetworkManager.DisconnectType.ClientInitiated
466 || args.Reason == NetworkManager.DisconnectType.ServerInitiated 558 || args.Reason == NetworkManager.DisconnectType.ServerInitiated
diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs
index dee02c3..5c3835b 100644
--- a/OpenSim/Tools/pCampBot/BotManager.cs
+++ b/OpenSim/Tools/pCampBot/BotManager.cs
@@ -52,9 +52,14 @@ 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. 55 /// Is pCampbot in the process of connecting bots?
56 /// </summary> 56 /// </summary>
57 public bool ShuttingDown { get; private set; } 57 public bool ConnectingBots { get; private set; }
58
59 /// <summary>
60 /// Is pCampbot in the process of disconnecting bots?
61 /// </summary>
62 public bool DisconnectingBots { get; private set; }
58 63
59 /// <summary> 64 /// <summary>
60 /// Delay between logins of multiple bots. 65 /// Delay between logins of multiple bots.
@@ -80,7 +85,7 @@ namespace pCampBot
80 /// <summary> 85 /// <summary>
81 /// Created bots, whether active or inactive. 86 /// Created bots, whether active or inactive.
82 /// </summary> 87 /// </summary>
83 protected List<Bot> m_lBot; 88 protected List<Bot> m_bots;
84 89
85 /// <summary> 90 /// <summary>
86 /// Random number generator. 91 /// Random number generator.
@@ -98,6 +103,46 @@ namespace pCampBot
98 public Dictionary<ulong, GridRegion> RegionsKnown { get; private set; } 103 public Dictionary<ulong, GridRegion> RegionsKnown { get; private set; }
99 104
100 /// <summary> 105 /// <summary>
106 /// First name for bots
107 /// </summary>
108 private string m_firstName;
109
110 /// <summary>
111 /// Last name stem for bots
112 /// </summary>
113 private string m_lastNameStem;
114
115 /// <summary>
116 /// Password for bots
117 /// </summary>
118 private string m_password;
119
120 /// <summary>
121 /// Login URI for bots.
122 /// </summary>
123 private string m_loginUri;
124
125 /// <summary>
126 /// Start location for bots.
127 /// </summary>
128 private string m_startUri;
129
130 /// <summary>
131 /// Postfix bot number at which bot sequence starts.
132 /// </summary>
133 private int m_fromBotNumber;
134
135 /// <summary>
136 /// Wear setting for bots.
137 /// </summary>
138 private string m_wearSetting;
139
140 /// <summary>
141 /// Behaviour switches for bots.
142 /// </summary>
143 private HashSet<string> m_behaviourSwitches = new HashSet<string>();
144
145 /// <summary>
101 /// 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
102 /// </summary> 147 /// </summary>
103 public BotManager() 148 public BotManager()
@@ -130,30 +175,47 @@ namespace pCampBot
130 } 175 }
131 } 176 }
132 177
133 m_console.Commands.AddCommand("bot", false, "shutdown", 178 m_console.Commands.AddCommand(
134 "shutdown", 179 "bot", false, "shutdown", "shutdown", "Shutdown bots and exit", HandleShutdown);
135 "Shutdown bots and exit", HandleShutdown); 180
181 m_console.Commands.AddCommand(
182 "bot", false, "quit", "quit", "Shutdown bots and exit", HandleShutdown);
136 183
137 m_console.Commands.AddCommand("bot", false, "quit", 184 m_console.Commands.AddCommand(
138 "quit", 185 "bot", false, "connect", "connect [<n>]", "Connect bots",
139 "Shutdown bots and exit", 186 "If an <n> is given, then the first <n> disconnected bots by postfix number are connected.\n"
140 HandleShutdown); 187 + "If no <n> is given, then all currently disconnected bots are connected.",
188 HandleConnect);
141 189
142 m_console.Commands.AddCommand("bot", false, "show regions", 190 m_console.Commands.AddCommand(
143 "show regions", 191 "bot", false, "disconnect", "disconnect [<n>]", "Disconnect bots",
144 "Show regions known to bots", 192 "Disconnecting bots will interupt any bot connection process, including connection on startup.\n"
145 HandleShowRegions); 193 + "If an <n> is given, then the last <n> connected bots by postfix number are disconnected.\n"
194 + "If no <n> is given, then all currently connected bots are disconnected.",
195 HandleDisconnect);
146 196
147 m_console.Commands.AddCommand("bot", false, "show bots", 197 m_console.Commands.AddCommand(
148 "show bots", 198 "bot", false, "sit", "sit", "Sit all bots on the ground.",
149 "Shows the status of all bots", 199 HandleSit);
150 HandleShowStatus);
151 200
152// m_console.Commands.AddCommand("bot", false, "add bots", 201 m_console.Commands.AddCommand(
153// "add bots <number>", 202 "bot", false, "stand", "stand", "Stand all bots.",
154// "Add more bots", HandleAddBots); 203 HandleStand);
155 204
156 m_lBot = new List<Bot>(); 205 m_console.Commands.AddCommand(
206 "bot", false, "set bots", "set bots <key> <value>", "Set a setting for all bots.", HandleSetBots);
207
208 m_console.Commands.AddCommand(
209 "bot", false, "show regions", "show regions", "Show regions known to bots", HandleShowRegions);
210
211 m_console.Commands.AddCommand(
212 "bot", false, "show bots", "show bots", "Shows the status of all bots", HandleShowBotsStatus);
213
214 m_console.Commands.AddCommand(
215 "bot", false, "show bot", "show bot <n>",
216 "Shows the detailed status and settings of a particular bot.", HandleShowBotStatus);
217
218 m_bots = new List<Bot>();
157 } 219 }
158 220
159 /// <summary> 221 /// <summary>
@@ -161,62 +223,102 @@ namespace pCampBot
161 /// </summary> 223 /// </summary>
162 /// <param name="botcount">How many bots to start up</param> 224 /// <param name="botcount">How many bots to start up</param>
163 /// <param name="cs">The configuration for the bots to use</param> 225 /// <param name="cs">The configuration for the bots to use</param>
164 public void dobotStartup(int botcount, IConfig startupConfig) 226 public void CreateBots(int botcount, IConfig startupConfig)
165 { 227 {
166 string firstName = startupConfig.GetString("firstname"); 228 m_firstName = startupConfig.GetString("firstname");
167 string lastNameStem = startupConfig.GetString("lastname"); 229 m_lastNameStem = startupConfig.GetString("lastname");
168 string password = startupConfig.GetString("password"); 230 m_password = startupConfig.GetString("password");
169 string loginUri = startupConfig.GetString("loginuri"); 231 m_loginUri = startupConfig.GetString("loginuri");
170 string startLocation = startupConfig.GetString("start", "last"); 232 m_fromBotNumber = startupConfig.GetInt("from", 0);
171 int fromBotNumber = startupConfig.GetInt("from", 0); 233 m_wearSetting = startupConfig.GetString("wear", "no");
172 string wearSetting = startupConfig.GetString("wear", "no");
173 234
174 string startUri = ParseInputStartLocationToUri(startLocation); 235 m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last"));
175 236
176 HashSet<string> behaviourSwitches = new HashSet<string>();
177 Array.ForEach<string>( 237 Array.ForEach<string>(
178 startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => behaviourSwitches.Add(b)); 238 startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_behaviourSwitches.Add(b));
239
240 for (int i = 0; i < botcount; i++)
241 {
242 lock (m_bots)
243 {
244 string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber);
245
246 // We must give each bot its own list of instantiated behaviours since they store state.
247 List<IBehaviour> behaviours = new List<IBehaviour>();
248
249 // Hard-coded for now
250 if (m_behaviourSwitches.Contains("c"))
251 behaviours.Add(new CrossBehaviour());
252
253 if (m_behaviourSwitches.Contains("g"))
254 behaviours.Add(new GrabbingBehaviour());
255
256 if (m_behaviourSwitches.Contains("n"))
257 behaviours.Add(new NoneBehaviour());
258
259 if (m_behaviourSwitches.Contains("p"))
260 behaviours.Add(new PhysicsBehaviour());
261
262 if (m_behaviourSwitches.Contains("t"))
263 behaviours.Add(new TeleportBehaviour());
264
265 CreateBot(this, behaviours, m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
266 }
267 }
268 }
179 269
270 public void ConnectBots(int botcount)
271 {
272 ConnectingBots = true;
273
274 Thread connectBotThread = new Thread(o => ConnectBotsInternal(botcount));
275
276 connectBotThread.Name = "Bots connection thread";
277 connectBotThread.Start();
278 }
279
280 private void ConnectBotsInternal(int botCount)
281 {
180 MainConsole.Instance.OutputFormat( 282 MainConsole.Instance.OutputFormat(
181 "[BOT MANAGER]: Starting {0} bots connecting to {1}, location {2}, named {3} {4}_<n>", 283 "[BOT MANAGER]: Starting {0} bots connecting to {1}, location {2}, named {3} {4}_<n>",
182 botcount, 284 botCount,
183 loginUri, 285 m_loginUri,
184 startUri, 286 m_startUri,
185 firstName, 287 m_firstName,
186 lastNameStem); 288 m_lastNameStem);
187 289
188 MainConsole.Instance.OutputFormat("[BOT MANAGER]: Delay between logins is {0}ms", LoginDelay); 290 MainConsole.Instance.OutputFormat("[BOT MANAGER]: Delay between logins is {0}ms", LoginDelay);
189 MainConsole.Instance.OutputFormat("[BOT MANAGER]: BotsSendAgentUpdates is {0}", InitBotSendAgentUpdates); 291 MainConsole.Instance.OutputFormat("[BOT MANAGER]: BotsSendAgentUpdates is {0}", InitBotSendAgentUpdates);
190 MainConsole.Instance.OutputFormat("[BOT MANAGER]: InitBotRequestObjectTextures is {0}", InitBotRequestObjectTextures); 292 MainConsole.Instance.OutputFormat("[BOT MANAGER]: InitBotRequestObjectTextures is {0}", InitBotRequestObjectTextures);
191 293
192 for (int i = 0; i < botcount; i++) 294 int connectedBots = 0;
193 {
194 if (ShuttingDown)
195 break;
196
197 string lastName = string.Format("{0}_{1}", lastNameStem, i + fromBotNumber);
198
199 // We must give each bot its own list of instantiated behaviours since they store state.
200 List<IBehaviour> behaviours = new List<IBehaviour>();
201
202 // Hard-coded for now
203 if (behaviourSwitches.Contains("c"))
204 behaviours.Add(new CrossBehaviour());
205 295
206 if (behaviourSwitches.Contains("g")) 296 for (int i = 0; i < m_bots.Count; i++)
207 behaviours.Add(new GrabbingBehaviour()); 297 {
298 lock (m_bots)
299 {
300 if (DisconnectingBots)
301 {
302 MainConsole.Instance.Output(
303 "[BOT MANAGER]: Aborting bot connection due to user-initiated disconnection");
304 break;
305 }
208 306
209 if (behaviourSwitches.Contains("n")) 307 if (m_bots[i].ConnectionState == ConnectionState.Disconnected)
210 behaviours.Add(new NoneBehaviour()); 308 {
309 m_bots[i].Connect();
310 connectedBots++;
211 311
212 if (behaviourSwitches.Contains("p")) 312 if (connectedBots >= botCount)
213 behaviours.Add(new PhysicsBehaviour()); 313 break;
214
215 if (behaviourSwitches.Contains("t"))
216 behaviours.Add(new TeleportBehaviour());
217 314
218 StartBot(this, behaviours, firstName, lastName, password, loginUri, startUri, wearSetting); 315 // Stagger logins
316 Thread.Sleep(LoginDelay);
317 }
318 }
219 } 319 }
320
321 ConnectingBots = false;
220 } 322 }
221 323
222 /// <summary> 324 /// <summary>
@@ -258,28 +360,8 @@ namespace pCampBot
258 return string.Format("uri:{0}&{1}&{2}&{3}", regionName, startPos.X, startPos.Y, startPos.Z); 360 return string.Format("uri:{0}&{1}&{2}&{3}", regionName, startPos.X, startPos.Y, startPos.Z);
259 } 361 }
260 362
261// /// <summary>
262// /// Add additional bots (and threads) to our bot pool
263// /// </summary>
264// /// <param name="botcount">How Many of them to add</param>
265// public void addbots(int botcount)
266// {
267// int len = m_td.Length;
268// Thread[] m_td2 = new Thread[len + botcount];
269// for (int i = 0; i < len; i++)
270// {
271// m_td2[i] = m_td[i];
272// }
273// m_td = m_td2;
274// int newlen = len + botcount;
275// for (int i = len; i < newlen; i++)
276// {
277// startupBot(Config);
278// }
279// }
280
281 /// <summary> 363 /// <summary>
282 /// This starts up the bot and stores the thread for the bot in the thread array 364 /// This creates a bot but does not start it.
283 /// </summary> 365 /// </summary>
284 /// <param name="bm"></param> 366 /// <param name="bm"></param>
285 /// <param name="behaviours">Behaviours for this bot to perform.</param> 367 /// <param name="behaviours">Behaviours for this bot to perform.</param>
@@ -289,12 +371,12 @@ namespace pCampBot
289 /// <param name="loginUri">Login URI</param> 371 /// <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> 372 /// <param name="startLocation">Location to start the bot. Can be "last", "home" or a specific sim name.</param>
291 /// <param name="wearSetting"></param> 373 /// <param name="wearSetting"></param>
292 public void StartBot( 374 public void CreateBot(
293 BotManager bm, List<IBehaviour> behaviours, 375 BotManager bm, List<IBehaviour> behaviours,
294 string firstName, string lastName, string password, string loginUri, string startLocation, string wearSetting) 376 string firstName, string lastName, string password, string loginUri, string startLocation, string wearSetting)
295 { 377 {
296 MainConsole.Instance.OutputFormat( 378 MainConsole.Instance.OutputFormat(
297 "[BOT MANAGER]: Starting bot {0} {1}, behaviours are {2}", 379 "[BOT MANAGER]: Creating bot {0} {1}, behaviours are {2}",
298 firstName, lastName, string.Join(",", behaviours.ConvertAll<string>(b => b.Name).ToArray())); 380 firstName, lastName, string.Join(",", behaviours.ConvertAll<string>(b => b.Name).ToArray()));
299 381
300 Bot pb = new Bot(bm, behaviours, firstName, lastName, password, startLocation, loginUri); 382 Bot pb = new Bot(bm, behaviours, firstName, lastName, password, startLocation, loginUri);
@@ -305,17 +387,7 @@ namespace pCampBot
305 pb.OnConnected += handlebotEvent; 387 pb.OnConnected += handlebotEvent;
306 pb.OnDisconnected += handlebotEvent; 388 pb.OnDisconnected += handlebotEvent;
307 389
308 lock (m_lBot) 390 m_bots.Add(pb);
309 m_lBot.Add(pb);
310
311 Thread pbThread = new Thread(pb.startup);
312 pbThread.Name = pb.Name;
313 pbThread.IsBackground = true;
314
315 pbThread.Start();
316
317 // Stagger logins
318 Thread.Sleep(LoginDelay);
319 } 391 }
320 392
321 /// <summary> 393 /// <summary>
@@ -328,54 +400,158 @@ namespace pCampBot
328 switch (eventt) 400 switch (eventt)
329 { 401 {
330 case EventType.CONNECTED: 402 case EventType.CONNECTED:
403 {
331 m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Connected"); 404 m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Connected");
332 break; 405 break;
406 }
407
333 case EventType.DISCONNECTED: 408 case EventType.DISCONNECTED:
409 {
334 m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Disconnected"); 410 m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Disconnected");
335 411 break;
336 lock (m_lBot) 412 }
337 {
338 if (m_lBot.TrueForAll(b => b.ConnectionState == ConnectionState.Disconnected))
339 Environment.Exit(0);
340
341 break;
342 }
343 } 413 }
344 } 414 }
345 415
346 /// <summary> 416 /// <summary>
347 /// Shut down all bots 417 /// Standard CreateConsole routine
348 /// </summary> 418 /// </summary>
349 /// <remarks> 419 /// <returns></returns>
350 /// We launch each shutdown on its own thread so that a slow shutting down bot doesn't hold up all the others. 420 protected CommandConsole CreateConsole()
351 /// </remarks> 421 {
352 public void doBotShutdown() 422 return new LocalConsole("pCampbot");
423 }
424
425 private void HandleConnect(string module, string[] cmd)
426 {
427 if (ConnectingBots)
428 {
429 MainConsole.Instance.Output("Still connecting bots. Please wait for previous process to complete.");
430 return;
431 }
432
433 lock (m_bots)
434 {
435 int botsToConnect;
436 int disconnectedBots = m_bots.Count(b => b.ConnectionState == ConnectionState.Disconnected);
437
438 if (cmd.Length == 1)
439 {
440 botsToConnect = disconnectedBots;
441 }
442 else
443 {
444 if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[1], out botsToConnect))
445 return;
446
447 botsToConnect = Math.Min(botsToConnect, disconnectedBots);
448 }
449
450 MainConsole.Instance.OutputFormat("Connecting {0} bots", botsToConnect);
451
452 ConnectBots(botsToConnect);
453 }
454 }
455
456 private void HandleDisconnect(string module, string[] cmd)
353 { 457 {
354 lock (m_lBot) 458 lock (m_bots)
355 { 459 {
356 foreach (Bot bot in m_lBot) 460 int botsToDisconnect;
461 int connectedBots = m_bots.Count(b => b.ConnectionState == ConnectionState.Connected);
462
463 if (cmd.Length == 1)
464 {
465 botsToDisconnect = connectedBots;
466 }
467 else
468 {
469 if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[1], out botsToDisconnect))
470 return;
471
472 botsToDisconnect = Math.Min(botsToDisconnect, connectedBots);
473 }
474
475 DisconnectingBots = true;
476
477 MainConsole.Instance.OutputFormat("Disconnecting {0} bots", botsToDisconnect);
478
479 int disconnectedBots = 0;
480
481 for (int i = m_bots.Count - 1; i >= 0; i--)
357 { 482 {
358 Bot thisBot = bot; 483 if (disconnectedBots >= botsToDisconnect)
359 Util.FireAndForget(o => thisBot.shutdown()); 484 break;
485
486 Bot thisBot = m_bots[i];
487
488 if (thisBot.ConnectionState == ConnectionState.Connected)
489 {
490 Util.FireAndForget(o => thisBot.Disconnect());
491 disconnectedBots++;
492 }
360 } 493 }
494
495 DisconnectingBots = false;
361 } 496 }
362 } 497 }
363 498
364 /// <summary> 499 private void HandleSit(string module, string[] cmd)
365 /// Standard CreateConsole routine
366 /// </summary>
367 /// <returns></returns>
368 protected CommandConsole CreateConsole()
369 { 500 {
370 return new LocalConsole("pCampbot"); 501 lock (m_bots)
502 {
503 m_bots.ForEach(b => b.SitOnGround());
504 }
505 }
506
507 private void HandleStand(string module, string[] cmd)
508 {
509 lock (m_bots)
510 {
511 m_bots.ForEach(b => b.Stand());
512 }
371 } 513 }
372 514
373 private void HandleShutdown(string module, string[] cmd) 515 private void HandleShutdown(string module, string[] cmd)
374 { 516 {
517 lock (m_bots)
518 {
519 int connectedBots = m_bots.Count(b => b.ConnectionState == ConnectionState.Connected);
520
521 if (connectedBots > 0)
522 {
523 MainConsole.Instance.OutputFormat("Please disconnect {0} connected bots first", connectedBots);
524 return;
525 }
526 }
527
375 MainConsole.Instance.Output("Shutting down"); 528 MainConsole.Instance.Output("Shutting down");
376 529
377 ShuttingDown = true; 530 Environment.Exit(0);
378 doBotShutdown(); 531 }
532
533 private void HandleSetBots(string module, string[] cmd)
534 {
535 string key = cmd[2];
536 string rawValue = cmd[3];
537
538 if (key == "SEND_AGENT_UPDATES")
539 {
540 bool newSendAgentUpdatesSetting;
541
542 if (!ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, rawValue, out newSendAgentUpdatesSetting))
543 return;
544
545 MainConsole.Instance.OutputFormat(
546 "Setting SEND_AGENT_UPDATES to {0} for all bots", newSendAgentUpdatesSetting);
547
548 lock (m_bots)
549 m_bots.ForEach(b => b.Client.Settings.SEND_AGENT_UPDATES = newSendAgentUpdatesSetting);
550 }
551 else
552 {
553 MainConsole.Instance.Output("Error: Only setting currently available is SEND_AGENT_UPDATES");
554 }
379 } 555 }
380 556
381 private void HandleShowRegions(string module, string[] cmd) 557 private void HandleShowRegions(string module, string[] cmd)
@@ -393,56 +569,87 @@ namespace pCampBot
393 } 569 }
394 } 570 }
395 571
396 private void HandleShowStatus(string module, string[] cmd) 572 private void HandleShowBotsStatus(string module, string[] cmd)
397 { 573 {
398 string outputFormat = "{0,-30} {1, -30} {2,-14}"; 574 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
399 MainConsole.Instance.OutputFormat(outputFormat, "Name", "Region", "Status"); 575 cdt.AddColumn("Name", 30);
576 cdt.AddColumn("Region", 30);
577 cdt.AddColumn("Status", 14);
578 cdt.AddColumn("Connections", 11);
400 579
401 Dictionary<ConnectionState, int> totals = new Dictionary<ConnectionState, int>(); 580 Dictionary<ConnectionState, int> totals = new Dictionary<ConnectionState, int>();
402 foreach (object o in Enum.GetValues(typeof(ConnectionState))) 581 foreach (object o in Enum.GetValues(typeof(ConnectionState)))
403 totals[(ConnectionState)o] = 0; 582 totals[(ConnectionState)o] = 0;
404 583
405 lock (m_lBot) 584 lock (m_bots)
406 { 585 {
407 foreach (Bot pb in m_lBot) 586 foreach (Bot pb in m_bots)
408 { 587 {
409 Simulator currentSim = pb.Client.Network.CurrentSim; 588 Simulator currentSim = pb.Client.Network.CurrentSim;
410 totals[pb.ConnectionState]++; 589 totals[pb.ConnectionState]++;
411 590
412 MainConsole.Instance.OutputFormat( 591 cdt.AddRow(
413 outputFormat, 592 pb.Name, currentSim != null ? currentSim.Name : "(none)", pb.ConnectionState, pb.SimulatorsCount);
414 pb.Name, currentSim != null ? currentSim.Name : "(none)", pb.ConnectionState);
415 } 593 }
416 } 594 }
417 595
596 MainConsole.Instance.Output(cdt.ToString());
597
418 ConsoleDisplayList cdl = new ConsoleDisplayList(); 598 ConsoleDisplayList cdl = new ConsoleDisplayList();
419 599
420 foreach (KeyValuePair<ConnectionState, int> kvp in totals) 600 foreach (KeyValuePair<ConnectionState, int> kvp in totals)
421 cdl.AddRow(kvp.Key, kvp.Value); 601 cdl.AddRow(kvp.Key, kvp.Value);
422 602
423 603 MainConsole.Instance.Output(cdl.ToString());
424 MainConsole.Instance.OutputFormat("\n{0}", cdl.ToString());
425 } 604 }
426 605
427 /* 606 private void HandleShowBotStatus(string module, string[] cmd)
428 private void HandleQuit(string module, string[] cmd)
429 { 607 {
430 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"); 608 if (cmd.Length != 3)
431 Environment.Exit(0); 609 {
610 MainConsole.Instance.Output("Usage: show bot <n>");
611 return;
612 }
613
614 int botNumber;
615
616 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber))
617 return;
618
619 string name = string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber);
620
621 Bot bot;
622
623 lock (m_bots)
624 bot = m_bots.Find(b => b.Name == name);
625
626 if (bot == null)
627 {
628 MainConsole.Instance.Output("No bot found with name {0}", name);
629 return;
630 }
631
632 ConsoleDisplayList cdl = new ConsoleDisplayList();
633 cdl.AddRow("Name", bot.Name);
634 cdl.AddRow("Status", bot.ConnectionState);
635
636 Simulator currentSim = bot.Client.Network.CurrentSim;
637 cdl.AddRow("Region", currentSim != null ? currentSim.Name : "(none)");
638
639 List<Simulator> connectedSimulators = bot.Simulators;
640 List<string> simulatorNames = connectedSimulators.ConvertAll<string>(cs => cs.Name);
641 cdl.AddRow("Connections", string.Join(", ", simulatorNames.ToArray()));
642
643 MainConsole.Instance.Output(cdl.ToString());
644
645 MainConsole.Instance.Output("Settings");
646
647 ConsoleDisplayList statusCdl = new ConsoleDisplayList();
648 GridClient botClient = bot.Client;
649 statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES);
650
651 MainConsole.Instance.Output(statusCdl.ToString());
432 } 652 }
433 */
434//
435// private void HandleAddBots(string module, string[] cmd)
436// {
437// int newbots = 0;
438//
439// if (cmd.Length > 2)
440// {
441// Int32.TryParse(cmd[2], out newbots);
442// }
443// if (newbots > 0)
444// addbots(newbots);
445// }
446 653
447 internal void Grid_GridRegion(object o, GridRegionEventArgs args) 654 internal void Grid_GridRegion(object o, GridRegionEventArgs args)
448 { 655 {
@@ -463,4 +670,4 @@ namespace pCampBot
463 } 670 }
464 } 671 }
465 } 672 }
466} 673} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/pCampBot.cs b/OpenSim/Tools/pCampBot/pCampBot.cs
index b02f917..781bb00 100644
--- a/OpenSim/Tools/pCampBot/pCampBot.cs
+++ b/OpenSim/Tools/pCampBot/pCampBot.cs
@@ -51,7 +51,7 @@ namespace pCampBot
51 { 51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 public const string ConfigFileName = "pCampbot.ini"; 54 public const string ConfigFileName = "pCampBot.ini";
55 55
56 [STAThread] 56 [STAThread]
57 public static void Main(string[] args) 57 public static void Main(string[] args)
@@ -82,6 +82,13 @@ namespace pCampBot
82 82
83 IConfigSource configSource = new IniConfigSource(iniFilePath); 83 IConfigSource configSource = new IniConfigSource(iniFilePath);
84 84
85 IConfig botManagerConfig = configSource.Configs["BotManager"];
86
87 if (botManagerConfig != null)
88 {
89 bm.LoginDelay = botManagerConfig.GetInt("LoginDelay", bm.LoginDelay);
90 }
91
85 IConfig botConfig = configSource.Configs["Bot"]; 92 IConfig botConfig = configSource.Configs["Bot"];
86 93
87 if (botConfig != null) 94 if (botConfig != null)
@@ -94,11 +101,12 @@ namespace pCampBot
94 } 101 }
95 102
96 int botcount = commandLineConfig.GetInt("botcount", 1); 103 int botcount = commandLineConfig.GetInt("botcount", 1);
104 bool startConnected = commandLineConfig.Get("connect") != null;
105
106 bm.CreateBots(botcount, commandLineConfig);
97 107
98 //startup specified number of bots. 1 is the default 108 if (startConnected)
99 Thread startBotThread = new Thread(o => bm.dobotStartup(botcount, commandLineConfig)); 109 bm.ConnectBots(botcount);
100 startBotThread.Name = "Initial start bots thread";
101 startBotThread.Start();
102 110
103 while (true) 111 while (true)
104 { 112 {
@@ -119,6 +127,7 @@ namespace pCampBot
119 //Set up our nifty config.. thanks to nini 127 //Set up our nifty config.. thanks to nini
120 ArgvConfigSource cs = new ArgvConfigSource(args); 128 ArgvConfigSource cs = new ArgvConfigSource(args);
121 129
130 cs.AddSwitch("Startup", "connect", "c");
122 cs.AddSwitch("Startup", "botcount", "n"); 131 cs.AddSwitch("Startup", "botcount", "n");
123 cs.AddSwitch("Startup", "from", "f"); 132 cs.AddSwitch("Startup", "from", "f");
124 cs.AddSwitch("Startup", "loginuri", "l"); 133 cs.AddSwitch("Startup", "loginuri", "l");
@@ -145,20 +154,21 @@ namespace pCampBot
145 "usage: pCampBot <-loginuri loginuri> [OPTIONS]\n" 154 "usage: pCampBot <-loginuri loginuri> [OPTIONS]\n"
146 + "Spawns a set of bots to test an OpenSim region\n\n" 155 + "Spawns a set of bots to test an OpenSim region\n\n"
147 + " -l, -loginuri loginuri for grid/standalone (required)\n" 156 + " -l, -loginuri loginuri for grid/standalone (required)\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" 157 + " -s, -start start location for bots (optional). Can be \"last\", \"home\" or a specific location with or without co-ords (e.g. \"region1\" or \"region2/50/30/90\"\n"
149 + " -firstname first name for the bots\n" 158 + " -firstname first name for the bots (required)\n"
150 + " -lastname lastname for the bots. Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n" 159 + " -lastname lastname for the bots (required). Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n"
151 + " -password password for the bots\n" 160 + " -password password for the bots (required)\n"
152 + " -n, -botcount optional number of bots to start (default: 1)\n" 161 + " -n, -botcount number of bots to start (default: 1) (optional)\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)" 162 + " -f, -from starting number for login bot names, e.g. 25 will login Ima Bot_25, Ima Bot_26, etc. (default: 0) (optional)\n"
154 + " -b, behaviours behaviours for bots. Comma separated, e.g. p,g. Default is p\n" 163 + " -c, -connect connect all bots at startup (optional)\n"
164 + " -b, behaviours behaviours for bots. Comma separated, e.g. p,g. Default is p (required)\n"
155 + " current options are:\n" 165 + " current options are:\n"
156 + " p (physics - bots constantly move and jump around)\n" 166 + " p (physics - bots constantly move and jump around)\n"
157 + " g (grab - bots randomly click prims whether set clickable or not)\n" 167 + " g (grab - bots randomly click prims whether set clickable or not)\n"
158 + " n (none - bots do nothing)\n" 168 + " n (none - bots do nothing)\n"
159 + " t (teleport - bots regularly teleport between regions on the grid)\n" 169 + " t (teleport - bots regularly teleport between regions on the grid)\n"
160// " c (cross)" + 170// " c (cross)\n" +
161 + " -wear optional folder from which to load appearance data, \"no\" if there is no such folder (default: no)\n" 171 + " -wear folder from which to load appearance data, \"no\" if there is no such folder (default: no) (optional)\n"
162 + " -h, -help show this message.\n"); 172 + " -h, -help show this message.\n");
163 } 173 }
164 } 174 }