aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs9
-rw-r--r--OpenSim/Data/IRegionData.cs1
-rw-r--r--OpenSim/Data/MSSQL/MSSQLRegionData.cs5
-rw-r--r--OpenSim/Data/MySQL/MySQLRegionData.cs5
-rw-r--r--OpenSim/Data/Null/NullRegionData.cs5
-rw-r--r--OpenSim/Framework/RegionFlags.cs3
-rw-r--r--OpenSim/Framework/Util.cs12
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs29
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs14
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs5
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs82
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs15
-rw-r--r--OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs9
-rw-r--r--OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs33
-rw-r--r--OpenSim/Services/Connectors/Grid/GridServicesConnector.cs51
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs6
-rw-r--r--OpenSim/Services/GridService/GridService.cs32
-rw-r--r--OpenSim/Services/GridService/HypergridLinker.cs2
-rw-r--r--OpenSim/Services/HypergridService/GatekeeperService.cs2
-rw-r--r--OpenSim/Services/Interfaces/IGridService.cs1
-rw-r--r--OpenSim/Services/UserAccountService/GridUserService.cs38
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs7
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/CrossBehaviour.cs6
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs9
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs6
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs7
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs9
-rw-r--r--OpenSim/Tools/pCampBot/Bot.cs77
-rw-r--r--OpenSim/Tools/pCampBot/BotManager.cs243
-rw-r--r--OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs13
-rw-r--r--bin/Robust.HG.ini.example28
-rw-r--r--bin/Robust.ini.example20
-rw-r--r--bin/config-include/StandaloneCommon.ini.example20
37 files changed, 727 insertions, 114 deletions
diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs
index 4642b2a..7d48516 100644
--- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs
+++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs
@@ -623,10 +623,13 @@ namespace OpenSim.Groups
623 if (agent != null) 623 if (agent != null)
624 break; 624 break;
625 } 625 }
626 if (agent == null) // oops 626 if (agent != null)
627 return AgentID.ToString(); 627 return Util.ProduceUserUniversalIdentifier(agent);
628
629 // we don't know anything about this foreign user
630 // try asking the user management module, which may know more
631 return m_UserManagement.GetUserUUI(AgentID);
628 632
629 return Util.ProduceUserUniversalIdentifier(agent);
630 } 633 }
631 634
632 private string AgentUUIForOutside(string AgentIDStr) 635 private string AgentUUIForOutside(string AgentIDStr)
diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs
index 70e1065..463c621 100644
--- a/OpenSim/Data/IRegionData.cs
+++ b/OpenSim/Data/IRegionData.cs
@@ -81,6 +81,7 @@ namespace OpenSim.Data
81 bool Delete(UUID regionID); 81 bool Delete(UUID regionID);
82 82
83 List<RegionData> GetDefaultRegions(UUID scopeID); 83 List<RegionData> GetDefaultRegions(UUID scopeID);
84 List<RegionData> GetDefaultHypergridRegions(UUID scopeID);
84 List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y); 85 List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y);
85 List<RegionData> GetHyperlinks(UUID scopeID); 86 List<RegionData> GetHyperlinks(UUID scopeID);
86 } 87 }
diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
index 0d89706..c0589df 100644
--- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
@@ -315,6 +315,11 @@ namespace OpenSim.Data.MSSQL
315 return Get((int)RegionFlags.DefaultRegion, scopeID); 315 return Get((int)RegionFlags.DefaultRegion, scopeID);
316 } 316 }
317 317
318 public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
319 {
320 return Get((int)RegionFlags.DefaultHGRegion, scopeID);
321 }
322
318 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y) 323 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
319 { 324 {
320 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID); 325 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs
index a2d4ae4..2ad7590 100644
--- a/OpenSim/Data/MySQL/MySQLRegionData.cs
+++ b/OpenSim/Data/MySQL/MySQLRegionData.cs
@@ -310,6 +310,11 @@ namespace OpenSim.Data.MySQL
310 return Get((int)RegionFlags.DefaultRegion, scopeID); 310 return Get((int)RegionFlags.DefaultRegion, scopeID);
311 } 311 }
312 312
313 public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
314 {
315 return Get((int)RegionFlags.DefaultHGRegion, scopeID);
316 }
317
313 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y) 318 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
314 { 319 {
315 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID); 320 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
diff --git a/OpenSim/Data/Null/NullRegionData.cs b/OpenSim/Data/Null/NullRegionData.cs
index f707d98..d28cd99 100644
--- a/OpenSim/Data/Null/NullRegionData.cs
+++ b/OpenSim/Data/Null/NullRegionData.cs
@@ -239,6 +239,11 @@ namespace OpenSim.Data.Null
239 return Get((int)RegionFlags.DefaultRegion, scopeID); 239 return Get((int)RegionFlags.DefaultRegion, scopeID);
240 } 240 }
241 241
242 public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
243 {
244 return Get((int)RegionFlags.DefaultHGRegion, scopeID);
245 }
246
242 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y) 247 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
243 { 248 {
244 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID); 249 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
diff --git a/OpenSim/Framework/RegionFlags.cs b/OpenSim/Framework/RegionFlags.cs
index a3089b0..7c6569e 100644
--- a/OpenSim/Framework/RegionFlags.cs
+++ b/OpenSim/Framework/RegionFlags.cs
@@ -48,6 +48,7 @@ namespace OpenSim.Framework
48 NoMove = 64, // Don't allow moving this region 48 NoMove = 64, // Don't allow moving this region
49 Reservation = 128, // This is an inactive reservation 49 Reservation = 128, // This is an inactive reservation
50 Authenticate = 256, // Require authentication 50 Authenticate = 256, // Require authentication
51 Hyperlink = 512 // Record represents a HG link 51 Hyperlink = 512, // Record represents a HG link
52 DefaultHGRegion = 1024 // Record represents a default region for hypergrid teleports only.
52 } 53 }
53} \ No newline at end of file 54} \ No newline at end of file
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 7398b37..7db575b 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -130,7 +130,7 @@ namespace OpenSim.Framework
130 private static SmartThreadPool m_ThreadPool; 130 private static SmartThreadPool m_ThreadPool;
131 131
132 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC. 132 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC.
133 private static readonly DateTime unixEpoch = 133 public static readonly DateTime UnixEpoch =
134 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime(); 134 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
135 135
136 private static readonly string rawUUIDPattern 136 private static readonly string rawUUIDPattern
@@ -521,20 +521,18 @@ namespace OpenSim.Framework
521 521
522 public static int ToUnixTime(DateTime stamp) 522 public static int ToUnixTime(DateTime stamp)
523 { 523 {
524 TimeSpan t = stamp.ToUniversalTime() - unixEpoch; 524 TimeSpan t = stamp.ToUniversalTime() - UnixEpoch;
525 return (int) t.TotalSeconds; 525 return (int)t.TotalSeconds;
526 } 526 }
527 527
528 public static DateTime ToDateTime(ulong seconds) 528 public static DateTime ToDateTime(ulong seconds)
529 { 529 {
530 DateTime epoch = unixEpoch; 530 return UnixEpoch.AddSeconds(seconds);
531 return epoch.AddSeconds(seconds);
532 } 531 }
533 532
534 public static DateTime ToDateTime(int seconds) 533 public static DateTime ToDateTime(int seconds)
535 { 534 {
536 DateTime epoch = unixEpoch; 535 return UnixEpoch.AddSeconds(seconds);
537 return epoch.AddSeconds(seconds);
538 } 536 }
539 537
540 /// <summary> 538 /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index 626932f..b3b0b8a 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
76 } 76 }
77 77
78 [Test] 78 [Test]
79 public void AddForClient() 79 public void TestAddForClient()
80 { 80 {
81 TestHelpers.InMethod(); 81 TestHelpers.InMethod();
82// log4net.Config.XmlConfigurator.Configure(); 82// log4net.Config.XmlConfigurator.Configure();
@@ -88,7 +88,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
88 } 88 }
89 89
90 [Test] 90 [Test]
91 public void RemoveForClient() 91 public void TestRemoveForClient()
92 { 92 {
93 TestHelpers.InMethod(); 93 TestHelpers.InMethod();
94// TestHelpers.EnableLogging(); 94// TestHelpers.EnableLogging();
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 174642d..917f164 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -372,21 +372,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
372 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, 372 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type,
373 string message, ChatSourceType src, bool ignoreDistance) 373 string message, ChatSourceType src, bool ignoreDistance)
374 { 374 {
375 // don't send chat to child agents 375 if (presence.LifecycleState != ScenePresenceState.Running)
376 if (presence.IsChildAgent) return false; 376 return false;
377
378 Vector3 fromRegionPos = fromPos + regionPos;
379 Vector3 toRegionPos = presence.AbsolutePosition +
380 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
381 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
382 377
383 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); 378 if (!ignoreDistance)
384
385 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
386 type == ChatTypeEnum.Say && dis > m_saydistance ||
387 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
388 { 379 {
389 return false; 380 Vector3 fromRegionPos = fromPos + regionPos;
381 Vector3 toRegionPos = presence.AbsolutePosition +
382 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
383 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
384
385 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
386
387 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
388 type == ChatTypeEnum.Say && dis > m_saydistance ||
389 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
390 {
391 return false;
392 }
390 } 393 }
391 394
392 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView 395 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
index bf1cffb..56ff2bd 100644
--- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -1212,7 +1212,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
1212 json.Add("jsonrpc", OSD.FromString("2.0")); 1212 json.Add("jsonrpc", OSD.FromString("2.0"));
1213 json.Add("id", OSD.FromString(jsonId)); 1213 json.Add("id", OSD.FromString(jsonId));
1214 json.Add("method", OSD.FromString(method)); 1214 json.Add("method", OSD.FromString(method));
1215 // Experiment 1215
1216 json.Add("params", OSD.SerializeMembers(parameters)); 1216 json.Add("params", OSD.SerializeMembers(parameters));
1217 1217
1218 string jsonRequestData = OSDParser.SerializeJsonString(json); 1218 string jsonRequestData = OSDParser.SerializeJsonString(json);
@@ -1240,8 +1240,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
1240 } 1240 }
1241 1241
1242 Stream rstream = webResponse.GetResponseStream(); 1242 Stream rstream = webResponse.GetResponseStream();
1243 if (rstream.Length < 1)
1244 return false;
1245 1243
1246 OSDMap mret = new OSDMap(); 1244 OSDMap mret = new OSDMap();
1247 try 1245 try
@@ -1318,8 +1316,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
1318 } 1316 }
1319 1317
1320 Stream rstream = webResponse.GetResponseStream(); 1318 Stream rstream = webResponse.GetResponseStream();
1321 if (rstream.Length < 1)
1322 return false;
1323 1319
1324 OSDMap response = new OSDMap(); 1320 OSDMap response = new OSDMap();
1325 try 1321 try
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 1f3e7a1..ed14c12 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -925,6 +925,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
925 925
926 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 926 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
927 { 927 {
928 if (!sp.Scene.IncomingPreCloseAgent(sp))
929 return;
930
928 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before 931 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before
929 // they regard the new region as the current region after receiving the AgentMovementComplete 932 // they regard the new region as the current region after receiving the AgentMovementComplete
930 // response. If close is sent before then, it will cause the viewer to quit instead. 933 // response. If close is sent before then, it will cause the viewer to quit instead.
@@ -1087,6 +1090,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1087 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1090 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1088 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1091 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
1089 { 1092 {
1093 if (!sp.Scene.IncomingPreCloseAgent(sp))
1094 return;
1095
1090 // RED ALERT!!!! 1096 // RED ALERT!!!!
1091 // PLEASE DO NOT DECREASE THIS WAIT TIME UNDER ANY CIRCUMSTANCES. 1097 // PLEASE DO NOT DECREASE THIS WAIT TIME UNDER ANY CIRCUMSTANCES.
1092 // THE VIEWERS SEEM TO NEED SOME TIME AFTER RECEIVING MoveAgentIntoRegion 1098 // THE VIEWERS SEEM TO NEED SOME TIME AFTER RECEIVING MoveAgentIntoRegion
@@ -1100,6 +1106,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1100 // then this will be handled in IncomingCloseAgent under lock conditions 1106 // then this will be handled in IncomingCloseAgent under lock conditions
1101 m_log.DebugFormat( 1107 m_log.DebugFormat(
1102 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name); 1108 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
1109
1103 sp.Scene.IncomingCloseAgent(sp.UUID, false); 1110 sp.Scene.IncomingCloseAgent(sp.UUID, false);
1104 } 1111 }
1105 else 1112 else
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 7adb203..8c983e6 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -481,14 +481,20 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
481 481
482 public string GetUserUUI(UUID userID) 482 public string GetUserUUI(UUID userID)
483 { 483 {
484 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID);
485 if (account != null)
486 return userID.ToString();
487
488 UserData ud; 484 UserData ud;
489 lock (m_UserCache) 485 lock (m_UserCache)
490 m_UserCache.TryGetValue(userID, out ud); 486 m_UserCache.TryGetValue(userID, out ud);
491 487
488 if (ud == null) // It's not in the cache
489 {
490 string[] names = new string[2];
491 // This will pull the data from either UserAccounts or GridUser
492 // and stick it into the cache
493 TryGetUserNamesFromServices(userID, names);
494 lock (m_UserCache)
495 m_UserCache.TryGetValue(userID, out ud);
496 }
497
492 if (ud != null) 498 if (ud != null)
493 { 499 {
494 string homeURL = ud.HomeURL; 500 string homeURL = ud.HomeURL;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index 3849a3f..31ef79b 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -235,6 +235,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
235 return m_GridService.GetDefaultRegions(scopeID); 235 return m_GridService.GetDefaultRegions(scopeID);
236 } 236 }
237 237
238 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
239 {
240 return m_GridService.GetDefaultHypergridRegions(scopeID);
241 }
242
238 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 243 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
239 { 244 {
240 return m_GridService.GetFallbackRegions(scopeID, x, y); 245 return m_GridService.GetFallbackRegions(scopeID, x, y);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
index b2646ba..6a57d1f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
@@ -277,6 +277,26 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
277 return rinfo; 277 return rinfo;
278 } 278 }
279 279
280 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
281 {
282 List<GridRegion> rinfo = m_LocalGridService.GetDefaultHypergridRegions(scopeID);
283 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Local GetDefaultHypergridRegions {0} found {1} regions", name, rinfo.Count);
284 List<GridRegion> grinfo = m_RemoteGridService.GetDefaultHypergridRegions(scopeID);
285
286 if (grinfo != null)
287 {
288 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetDefaultHypergridRegions {0} found {1} regions", name, grinfo.Count);
289 foreach (GridRegion r in grinfo)
290 {
291 m_RegionInfoCache.Cache(r);
292 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null)
293 rinfo.Add(r);
294 }
295 }
296
297 return rinfo;
298 }
299
280 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 300 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
281 { 301 {
282 List<GridRegion> rinfo = m_LocalGridService.GetFallbackRegions(scopeID, x, y); 302 List<GridRegion> rinfo = m_LocalGridService.GetFallbackRegions(scopeID, x, y);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index f864392..18e7eb8 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3854,10 +3854,13 @@ namespace OpenSim.Region.Framework.Scenes
3854 3854
3855 // We need to ensure that we are not already removing the scene presence before we ask it not to be 3855 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3856 // closed. 3856 // closed.
3857 if (sp != null && sp.IsChildAgent && sp.LifecycleState == ScenePresenceState.Running) 3857 if (sp != null && sp.IsChildAgent
3858 && (sp.LifecycleState == ScenePresenceState.Running
3859 || sp.LifecycleState == ScenePresenceState.PreRemove))
3858 { 3860 {
3859 m_log.DebugFormat( 3861 m_log.DebugFormat(
3860 "[SCENE]: Reusing existing child scene presence for {0} in {1}", sp.Name, Name); 3862 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3863 sp.Name, sp.LifecycleState, Name);
3861 3864
3862 // In the case where, for example, an A B C D region layout, an avatar may 3865 // In the case where, for example, an A B C D region layout, an avatar may
3863 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C 3866 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
@@ -3879,6 +3882,8 @@ namespace OpenSim.Region.Framework.Scenes
3879// } 3882// }
3880// else if (EntityTransferModule.IsInTransit(sp.UUID)) 3883// else if (EntityTransferModule.IsInTransit(sp.UUID))
3881 3884
3885 sp.LifecycleState = ScenePresenceState.Running;
3886
3882 if (EntityTransferModule.IsInTransit(sp.UUID)) 3887 if (EntityTransferModule.IsInTransit(sp.UUID))
3883 { 3888 {
3884 sp.DoNotCloseAfterTeleport = true; 3889 sp.DoNotCloseAfterTeleport = true;
@@ -4018,6 +4023,19 @@ namespace OpenSim.Region.Framework.Scenes
4018 // uses down the line. 4023 // uses down the line.
4019 sp.TeleportFlags = (TPFlags)teleportFlags; 4024 sp.TeleportFlags = (TPFlags)teleportFlags;
4020 4025
4026 // We must carry out a further authorization check if there's an
4027 // attempt to make a child agent into a root agent, since SeeIntoRegion may have allowed a child
4028 // agent to login to a region where a full avatar would not be allowed.
4029 //
4030 // We determine whether this is a CreateAgent for a future non-child agent by inspecting
4031 // TeleportFlags, which will be default for a child connection. This relies on input from the source
4032 // region.
4033 if (sp.TeleportFlags != TPFlags.Default)
4034 {
4035 if (!AuthorizeUser(acd, false, out reason))
4036 return false;
4037 }
4038
4021 if (sp.IsChildAgent) 4039 if (sp.IsChildAgent)
4022 { 4040 {
4023 m_log.DebugFormat( 4041 m_log.DebugFormat(
@@ -4526,10 +4544,10 @@ namespace OpenSim.Region.Framework.Scenes
4526 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4544 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
4527 if (childAgentUpdate != null) 4545 if (childAgentUpdate != null)
4528 { 4546 {
4529 if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID) 4547// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4530 // Only warn for now 4548// // Only warn for now
4531 m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?", 4549// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4532 childAgentUpdate.UUID, cAgentData.SessionID); 4550// childAgentUpdate.UUID, cAgentData.SessionID);
4533 4551
4534 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4552 // I can't imagine *yet* why we would get an update if the agent is a root agent..
4535 // however to avoid a race condition crossing borders.. 4553 // however to avoid a race condition crossing borders..
@@ -4631,6 +4649,50 @@ namespace OpenSim.Region.Framework.Scenes
4631 } 4649 }
4632 4650
4633 /// <summary> 4651 /// <summary>
4652 /// Tell a single agent to prepare to close.
4653 /// </summary>
4654 /// <remarks>
4655 /// This should only be called if we may close the agent but there will be some delay in so doing. Meant for
4656 /// internal use - other callers should almost certainly called IncomingCloseAgent().
4657 /// </remarks>
4658 /// <param name="sp"></param>
4659 /// <returns>true if pre-close state notification was successful. false if the agent
4660 /// was not in a state where it could transition to pre-close.</returns>
4661 public bool IncomingPreCloseAgent(ScenePresence sp)
4662 {
4663 lock (m_removeClientLock)
4664 {
4665 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4666 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4667 // want to obey this close since C may have renewed the child agent lease on B.
4668 if (sp.DoNotCloseAfterTeleport)
4669 {
4670 m_log.DebugFormat(
4671 "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4672 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4673
4674 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4675 sp.DoNotCloseAfterTeleport = false;
4676
4677 return false;
4678 }
4679
4680 if (sp.LifecycleState != ScenePresenceState.Running)
4681 {
4682 m_log.DebugFormat(
4683 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4684 sp.Name, Name, sp.LifecycleState);
4685
4686 return false;
4687 }
4688
4689 sp.LifecycleState = ScenePresenceState.PreRemove;
4690
4691 return true;
4692 }
4693 }
4694
4695 /// <summary>
4634 /// Tell a single agent to disconnect from the region. 4696 /// Tell a single agent to disconnect from the region.
4635 /// </summary> 4697 /// </summary>
4636 /// <param name="agentID"></param> 4698 /// <param name="agentID"></param>
@@ -4649,16 +4711,16 @@ namespace OpenSim.Region.Framework.Scenes
4649 if (sp == null) 4711 if (sp == null)
4650 { 4712 {
4651 m_log.DebugFormat( 4713 m_log.DebugFormat(
4652 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in {1}", 4714 "[SCENE]: Called IncomingCloseAgent() with agent ID {0} but no such presence is in {1}",
4653 agentID, Name); 4715 agentID, Name);
4654 4716
4655 return false; 4717 return false;
4656 } 4718 }
4657 4719
4658 if (sp.LifecycleState != ScenePresenceState.Running) 4720 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4659 { 4721 {
4660 m_log.DebugFormat( 4722 m_log.DebugFormat(
4661 "[SCENE]: Called RemoveClient() for {0} in {1} but presence is already in state {2}", 4723 "[SCENE]: Called IncomingCloseAgent() for {0} in {1} but presence is already in state {2}",
4662 sp.Name, Name, sp.LifecycleState); 4724 sp.Name, Name, sp.LifecycleState);
4663 4725
4664 return false; 4726 return false;
@@ -6025,7 +6087,7 @@ Environment.Exit(1);
6025 { 6087 {
6026 if (!AuthorizeUser(aCircuit, false, out reason)) 6088 if (!AuthorizeUser(aCircuit, false, out reason))
6027 { 6089 {
6028 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6090 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
6029 return false; 6091 return false;
6030 } 6092 }
6031 } 6093 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
index dc3a212..cae7fe5 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
@@ -37,7 +37,8 @@ namespace OpenSim.Region.Framework.Scenes
37 /// This is a state machine. 37 /// This is a state machine.
38 /// 38 ///
39 /// [Entry] => Running 39 /// [Entry] => Running
40 /// Running => Removing 40 /// Running => PreRemove, Removing
41 /// PreRemove => Running, Removing
41 /// Removing => Removed 42 /// Removing => Removed
42 /// 43 ///
43 /// All other methods should only see the scene presence in running state - this is the normal operational state 44 /// All other methods should only see the scene presence in running state - this is the normal operational state
@@ -46,6 +47,7 @@ namespace OpenSim.Region.Framework.Scenes
46 public enum ScenePresenceState 47 public enum ScenePresenceState
47 { 48 {
48 Running, // Normal operation state. The scene presence is available. 49 Running, // Normal operation state. The scene presence is available.
50 PreRemove, // The presence is due to be removed but can still be returning to running.
49 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient. 51 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient.
50 Removed, // The presence has been removed from the scene and is effectively dead. 52 Removed, // The presence has been removed from the scene and is effectively dead.
51 // There is no exit from this state. 53 // There is no exit from this state.
@@ -80,8 +82,17 @@ namespace OpenSim.Region.Framework.Scenes
80 82
81 lock (this) 83 lock (this)
82 { 84 {
83 if (newState == ScenePresenceState.Removing && m_state == ScenePresenceState.Running) 85 if (newState == m_state)
86 return;
87 else if (newState == ScenePresenceState.Running && m_state == ScenePresenceState.PreRemove)
84 transitionOkay = true; 88 transitionOkay = true;
89 else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running)
90 transitionOkay = true;
91 else if (newState == ScenePresenceState.Removing)
92 {
93 if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove)
94 transitionOkay = true;
95 }
85 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing) 96 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
86 transitionOkay = true; 97 transitionOkay = true;
87 } 98 }
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
index 15dea17..1eb0a6b 100644
--- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -624,9 +624,16 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
624 int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum(); 624 int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
625 avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1); 625 avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
626 626
627 string childAgentStatus;
628
629 if (llClient.SceneAgent != null)
630 childAgentStatus = llClient.SceneAgent.IsChildAgent ? "N" : "Y";
631 else
632 childAgentStatus = "Off!";
633
627 m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", 634 m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}",
628 scene.RegionInfo.RegionName, llClient.Name, 635 scene.RegionInfo.RegionName, llClient.Name,
629 llClient.SceneAgent.IsChildAgent ? "N" : "Y", 636 childAgentStatus,
630 (DateTime.Now - cinfo.StartedTime).Minutes, 637 (DateTime.Now - cinfo.StartedTime).Minutes,
631 avg_reqs, 638 avg_reqs,
632 string.Format( 639 string.Format(
diff --git a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs
index 89cba8a..c63b409 100644
--- a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs
@@ -106,6 +106,9 @@ namespace OpenSim.Server.Handlers.Grid
106 case "get_default_regions": 106 case "get_default_regions":
107 return GetDefaultRegions(request); 107 return GetDefaultRegions(request);
108 108
109 case "get_default_hypergrid_regions":
110 return GetDefaultHypergridRegions(request);
111
109 case "get_fallback_regions": 112 case "get_fallback_regions":
110 return GetFallbackRegions(request); 113 return GetFallbackRegions(request);
111 114
@@ -444,6 +447,36 @@ namespace OpenSim.Server.Handlers.Grid
444 return Util.UTF8NoBomEncoding.GetBytes(xmlString); 447 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
445 } 448 }
446 449
450 byte[] GetDefaultHypergridRegions(Dictionary<string, object> request)
451 {
452 //m_log.DebugFormat("[GRID HANDLER]: GetDefaultRegions");
453 UUID scopeID = UUID.Zero;
454 if (request.ContainsKey("SCOPEID"))
455 UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
456 else
457 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get region range");
458
459 List<GridRegion> rinfos = m_GridService.GetDefaultHypergridRegions(scopeID);
460
461 Dictionary<string, object> result = new Dictionary<string, object>();
462 if ((rinfos == null) || ((rinfos != null) && (rinfos.Count == 0)))
463 result["result"] = "null";
464 else
465 {
466 int i = 0;
467 foreach (GridRegion rinfo in rinfos)
468 {
469 Dictionary<string, object> rinfoDict = rinfo.ToKeyValuePairs();
470 result["region" + i] = rinfoDict;
471 i++;
472 }
473 }
474 string xmlString = ServerUtils.BuildXmlResponse(result);
475
476 //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString);
477 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
478 }
479
447 byte[] GetFallbackRegions(Dictionary<string, object> request) 480 byte[] GetFallbackRegions(Dictionary<string, object> request)
448 { 481 {
449 //m_log.DebugFormat("[GRID HANDLER]: GetRegionRange"); 482 //m_log.DebugFormat("[GRID HANDLER]: GetRegionRange");
diff --git a/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs b/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
index f982cc1..af91cdb 100644
--- a/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
@@ -525,6 +525,57 @@ namespace OpenSim.Services.Connectors
525 return rinfos; 525 return rinfos;
526 } 526 }
527 527
528 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
529 {
530 Dictionary<string, object> sendData = new Dictionary<string, object>();
531
532 sendData["SCOPEID"] = scopeID.ToString();
533
534 sendData["METHOD"] = "get_default_hypergrid_regions";
535
536 List<GridRegion> rinfos = new List<GridRegion>();
537 string reply = string.Empty;
538 string uri = m_ServerURI + "/grid";
539 try
540 {
541 reply = SynchronousRestFormsRequester.MakeRequest("POST",
542 uri,
543 ServerUtils.BuildQueryString(sendData));
544
545 //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
546 }
547 catch (Exception e)
548 {
549 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
550 return rinfos;
551 }
552
553 if (reply != string.Empty)
554 {
555 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
556
557 if (replyData != null)
558 {
559 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
560 foreach (object r in rinfosList)
561 {
562 if (r is Dictionary<string, object>)
563 {
564 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
565 rinfos.Add(rinfo);
566 }
567 }
568 }
569 else
570 m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultHypergridRegions {0} received null response",
571 scopeID);
572 }
573 else
574 m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultHypergridRegions received null reply");
575
576 return rinfos;
577 }
578
528 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 579 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
529 { 580 {
530 Dictionary<string, object> sendData = new Dictionary<string, object>(); 581 Dictionary<string, object> sendData = new Dictionary<string, object>();
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index 043d131..36a5182 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -341,6 +341,12 @@ namespace OpenSim.Services.Connectors.SimianGrid
341 return new List<GridRegion>(0); 341 return new List<GridRegion>(0);
342 } 342 }
343 343
344 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
345 {
346 // TODO: Allow specifying the default grid location
347 return GetDefaultRegions(scopeID);
348 }
349
344 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 350 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
345 { 351 {
346 GridRegion defRegion = GetNearestRegion(new Vector3d(x, y, 0.0), true); 352 GridRegion defRegion = GetNearestRegion(new Vector3d(x, y, 0.0), true);
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index a1485c8..e72b7f9 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -265,8 +265,9 @@ namespace OpenSim.Services.GridService
265 m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e); 265 m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
266 } 266 }
267 267
268 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3}", 268 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3} with flags {4}",
269 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY); 269 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY,
270 (OpenSim.Framework.RegionFlags)flags);
270 271
271 return String.Empty; 272 return String.Empty;
272 } 273 }
@@ -478,6 +479,33 @@ namespace OpenSim.Services.GridService
478 return ret; 479 return ret;
479 } 480 }
480 481
482 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
483 {
484 List<GridRegion> ret = new List<GridRegion>();
485
486 List<RegionData> regions = m_Database.GetDefaultHypergridRegions(scopeID);
487
488 foreach (RegionData r in regions)
489 {
490 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
491 ret.Add(RegionData2RegionInfo(r));
492 }
493
494 int hgDefaultRegionsFoundOnline = regions.Count;
495
496 // For now, hypergrid default regions will always be given precedence but we will also return simple default
497 // regions in case no specific hypergrid regions are specified.
498 ret.AddRange(GetDefaultRegions(scopeID));
499
500 int normalDefaultRegionsFoundOnline = ret.Count - hgDefaultRegionsFoundOnline;
501
502 m_log.DebugFormat(
503 "[GRID SERVICE]: GetDefaultHypergridRegions returning {0} hypergrid default and {1} normal default regions",
504 hgDefaultRegionsFoundOnline, normalDefaultRegionsFoundOnline);
505
506 return ret;
507 }
508
481 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 509 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
482 { 510 {
483 List<GridRegion> ret = new List<GridRegion>(); 511 List<GridRegion> ret = new List<GridRegion>();
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
index 8335724..4024295 100644
--- a/OpenSim/Services/GridService/HypergridLinker.cs
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -79,7 +79,7 @@ namespace OpenSim.Services.GridService
79 { 79 {
80 if (m_DefaultRegion == null) 80 if (m_DefaultRegion == null)
81 { 81 {
82 List<GridRegion> defs = m_GridService.GetDefaultRegions(m_ScopeID); 82 List<GridRegion> defs = m_GridService.GetDefaultHypergridRegions(m_ScopeID);
83 if (defs != null && defs.Count > 0) 83 if (defs != null && defs.Count > 0)
84 m_DefaultRegion = defs[0]; 84 m_DefaultRegion = defs[0];
85 else 85 else
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs
index e10c4cb..f6136b5 100644
--- a/OpenSim/Services/HypergridService/GatekeeperService.cs
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -171,7 +171,7 @@ namespace OpenSim.Services.HypergridService
171 m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to link to {0}", (regionName == string.Empty)? "default region" : regionName); 171 m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to link to {0}", (regionName == string.Empty)? "default region" : regionName);
172 if (!m_AllowTeleportsToAnyRegion || regionName == string.Empty) 172 if (!m_AllowTeleportsToAnyRegion || regionName == string.Empty)
173 { 173 {
174 List<GridRegion> defs = m_GridService.GetDefaultRegions(m_ScopeID); 174 List<GridRegion> defs = m_GridService.GetDefaultHypergridRegions(m_ScopeID);
175 if (defs != null && defs.Count > 0) 175 if (defs != null && defs.Count > 0)
176 { 176 {
177 region = defs[0]; 177 region = defs[0];
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs
index cecbe9e..e3c70d3 100644
--- a/OpenSim/Services/Interfaces/IGridService.cs
+++ b/OpenSim/Services/Interfaces/IGridService.cs
@@ -97,6 +97,7 @@ namespace OpenSim.Services.Interfaces
97 List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax); 97 List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax);
98 98
99 List<GridRegion> GetDefaultRegions(UUID scopeID); 99 List<GridRegion> GetDefaultRegions(UUID scopeID);
100 List<GridRegion> GetDefaultHypergridRegions(UUID scopeID);
100 List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y); 101 List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y);
101 List<GridRegion> GetHyperlinks(UUID scopeID); 102 List<GridRegion> GetHyperlinks(UUID scopeID);
102 103
diff --git a/OpenSim/Services/UserAccountService/GridUserService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs
index b1cdd45..944411f 100644
--- a/OpenSim/Services/UserAccountService/GridUserService.cs
+++ b/OpenSim/Services/UserAccountService/GridUserService.cs
@@ -47,6 +47,44 @@ namespace OpenSim.Services.UserAccountService
47 public GridUserService(IConfigSource config) : base(config) 47 public GridUserService(IConfigSource config) : base(config)
48 { 48 {
49 m_log.Debug("[GRID USER SERVICE]: Starting user grid service"); 49 m_log.Debug("[GRID USER SERVICE]: Starting user grid service");
50
51 MainConsole.Instance.Commands.AddCommand(
52 "Users", false,
53 "show grid users online",
54 "show grid users online",
55 "Show number of grid users registered as online.",
56 "This number may not be accurate as a region may crash or not be cleanly shutdown and leave grid users shown as online\n."
57 + "For this reason, users online for more than 5 days are not currently counted",
58 HandleShowGridUsersOnline);
59 }
60
61 protected void HandleShowGridUsersOnline(string module, string[] cmdparams)
62 {
63// if (cmdparams.Length != 4)
64// {
65// MainConsole.Instance.Output("Usage: show grid users online");
66// return;
67// }
68
69// int onlineCount;
70 int onlineRecentlyCount = 0;
71
72 DateTime now = DateTime.UtcNow;
73
74 foreach (GridUserData gu in m_Database.GetAll(""))
75 {
76 if (bool.Parse(gu.Data["Online"]))
77 {
78// onlineCount++;
79
80 int unixLoginTime = int.Parse(gu.Data["Login"]);
81
82 if ((now - Util.ToDateTime(unixLoginTime)).Days < 5)
83 onlineRecentlyCount++;
84 }
85 }
86
87 MainConsole.Instance.OutputFormat("Users online: {0}", onlineRecentlyCount);
50 } 88 }
51 89
52 public virtual GridUserInfo GetGridUserInfo(string userID) 90 public virtual GridUserInfo GetGridUserInfo(string userID)
diff --git a/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs
index 9a9371d..9bc8512 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs
@@ -35,6 +35,11 @@ namespace pCampBot
35{ 35{
36 public class AbstractBehaviour : IBehaviour 36 public class AbstractBehaviour : IBehaviour
37 { 37 {
38 /// <summary>
39 /// Abbreviated name of this behaviour.
40 /// </summary>
41 public string AbbreviatedName { get; protected set; }
42
38 public string Name { get; protected set; } 43 public string Name { get; protected set; }
39 44
40 public Bot Bot { get; protected set; } 45 public Bot Bot { get; protected set; }
@@ -45,5 +50,7 @@ namespace pCampBot
45 { 50 {
46 Bot = bot; 51 Bot = bot;
47 } 52 }
53
54 public virtual void Close() {}
48 } 55 }
49} 56}
diff --git a/OpenSim/Tools/pCampBot/Behaviours/CrossBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/CrossBehaviour.cs
index 1e01c64..4d806fc 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/CrossBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/CrossBehaviour.cs
@@ -47,7 +47,11 @@ namespace pCampBot
47 47
48 public const int m_regionCrossingTimeout = 1000 * 60; 48 public const int m_regionCrossingTimeout = 1000 * 60;
49 49
50 public CrossBehaviour() { Name = "Cross"; } 50 public CrossBehaviour()
51 {
52 AbbreviatedName = "c";
53 Name = "Cross";
54 }
51 55
52 public override void Action() 56 public override void Action()
53 { 57 {
diff --git a/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs
index 66a336a..59f6244 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs
@@ -29,6 +29,7 @@ using OpenMetaverse;
29using System; 29using System;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq; 31using System.Linq;
32using System.Threading;
32using pCampBot.Interfaces; 33using pCampBot.Interfaces;
33 34
34namespace pCampBot 35namespace pCampBot
@@ -41,7 +42,11 @@ namespace pCampBot
41 /// </remarks> 42 /// </remarks>
42 public class GrabbingBehaviour : AbstractBehaviour 43 public class GrabbingBehaviour : AbstractBehaviour
43 { 44 {
44 public GrabbingBehaviour() { Name = "Grabbing"; } 45 public GrabbingBehaviour()
46 {
47 AbbreviatedName = "g";
48 Name = "Grabbing";
49 }
45 50
46 public override void Action() 51 public override void Action()
47 { 52 {
@@ -56,6 +61,8 @@ namespace pCampBot
56 Bot.Client.Self.Grab(prim.LocalID); 61 Bot.Client.Self.Grab(prim.LocalID);
57 Bot.Client.Self.GrabUpdate(prim.ID, Vector3.Zero); 62 Bot.Client.Self.GrabUpdate(prim.ID, Vector3.Zero);
58 Bot.Client.Self.DeGrab(prim.LocalID); 63 Bot.Client.Self.DeGrab(prim.LocalID);
64
65 Thread.Sleep(1000);
59 } 66 }
60 } 67 }
61} \ No newline at end of file 68} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs
index 9cf8a54..9a3075c 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs
@@ -38,6 +38,10 @@ namespace pCampBot
38 /// </summary> 38 /// </summary>
39 public class NoneBehaviour : AbstractBehaviour 39 public class NoneBehaviour : AbstractBehaviour
40 { 40 {
41 public NoneBehaviour() { Name = "None"; } 41 public NoneBehaviour()
42 {
43 AbbreviatedName = "n";
44 Name = "None";
45 }
42 } 46 }
43} \ No newline at end of file 47} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs
index daa7485..6fd2b7c 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs
@@ -46,6 +46,7 @@ namespace pCampBot
46 46
47 public PhysicsBehaviour() 47 public PhysicsBehaviour()
48 { 48 {
49 AbbreviatedName = "p";
49 Name = "Physics"; 50 Name = "Physics";
50 talkarray = readexcuses(); 51 talkarray = readexcuses();
51 } 52 }
@@ -77,6 +78,12 @@ namespace pCampBot
77 Bot.Client.Self.Chat(randomf, 0, ChatType.Normal); 78 Bot.Client.Self.Chat(randomf, 0, ChatType.Normal);
78 } 79 }
79 80
81 public override void Close()
82 {
83 if (Bot.ConnectionState == ConnectionState.Connected)
84 Bot.Client.Self.Jump(false);
85 }
86
80 private string[] readexcuses() 87 private string[] readexcuses()
81 { 88 {
82 string allexcuses = ""; 89 string allexcuses = "";
diff --git a/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs
index fbb4e96..81f250d 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq; 30using System.Linq;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using log4net; 33using log4net;
33using OpenMetaverse; 34using OpenMetaverse;
34using pCampBot.Interfaces; 35using pCampBot.Interfaces;
@@ -42,7 +43,11 @@ namespace pCampBot
42 { 43 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 45
45 public TeleportBehaviour() { Name = "Teleport"; } 46 public TeleportBehaviour()
47 {
48 AbbreviatedName = "t";
49 Name = "Teleport";
50 }
46 51
47 public override void Action() 52 public override void Action()
48 { 53 {
@@ -70,6 +75,8 @@ namespace pCampBot
70 Bot.Name, sourceRegion.Name, Bot.Client.Self.SimPosition, destRegion.Name, destPosition); 75 Bot.Name, sourceRegion.Name, Bot.Client.Self.SimPosition, destRegion.Name, destPosition);
71 76
72 Bot.Client.Self.Teleport(destRegion.RegionHandle, destPosition); 77 Bot.Client.Self.Teleport(destRegion.RegionHandle, destPosition);
78
79 Thread.Sleep(Bot.Random.Next(3000, 10000));
73 } 80 }
74 } 81 }
75} \ No newline at end of file 82} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/Bot.cs b/OpenSim/Tools/pCampBot/Bot.cs
index d418288..d0a4ef3 100644
--- a/OpenSim/Tools/pCampBot/Bot.cs
+++ b/OpenSim/Tools/pCampBot/Bot.cs
@@ -72,9 +72,10 @@ namespace pCampBot
72 /// Behaviours implemented by this bot. 72 /// Behaviours implemented by this bot.
73 /// </summary> 73 /// </summary>
74 /// <remarks> 74 /// <remarks>
75 /// Lock this list before manipulating it. 75 /// Indexed by abbreviated name. There can only be one instance of a particular behaviour.
76 /// Lock this structure before manipulating it.
76 /// </remarks> 77 /// </remarks>
77 public List<IBehaviour> Behaviours { get; private set; } 78 public Dictionary<string, IBehaviour> Behaviours { get; private set; }
78 79
79 /// <summary> 80 /// <summary>
80 /// Objects that the bot has discovered. 81 /// Objects that the bot has discovered.
@@ -165,8 +166,6 @@ namespace pCampBot
165 { 166 {
166 ConnectionState = ConnectionState.Disconnected; 167 ConnectionState = ConnectionState.Disconnected;
167 168
168 behaviours.ForEach(b => b.Initialize(this));
169
170 Random = new Random(Environment.TickCount);// We do stuff randomly here 169 Random = new Random(Environment.TickCount);// We do stuff randomly here
171 FirstName = firstName; 170 FirstName = firstName;
172 LastName = lastName; 171 LastName = lastName;
@@ -176,12 +175,53 @@ namespace pCampBot
176 StartLocation = startLocation; 175 StartLocation = startLocation;
177 176
178 Manager = bm; 177 Manager = bm;
179 Behaviours = behaviours; 178
179 Behaviours = new Dictionary<string, IBehaviour>();
180 foreach (IBehaviour behaviour in behaviours)
181 AddBehaviour(behaviour);
180 182
181 // Only calling for use as a template. 183 // Only calling for use as a template.
182 CreateLibOmvClient(); 184 CreateLibOmvClient();
183 } 185 }
184 186
187 public bool TryGetBehaviour(string abbreviatedName, out IBehaviour behaviour)
188 {
189 lock (Behaviours)
190 return Behaviours.TryGetValue(abbreviatedName, out behaviour);
191 }
192
193 public bool AddBehaviour(IBehaviour behaviour)
194 {
195 lock (Behaviours)
196 {
197 if (!Behaviours.ContainsKey(behaviour.AbbreviatedName))
198 {
199 behaviour.Initialize(this);
200 Behaviours.Add(behaviour.AbbreviatedName, behaviour);
201
202 return true;
203 }
204 }
205
206 return false;
207 }
208
209 public bool RemoveBehaviour(string abbreviatedName)
210 {
211 lock (Behaviours)
212 {
213 IBehaviour behaviour;
214
215 if (!Behaviours.TryGetValue(abbreviatedName, out behaviour))
216 return false;
217
218 behaviour.Close();
219 Behaviours.Remove(abbreviatedName);
220
221 return true;
222 }
223 }
224
185 private void CreateLibOmvClient() 225 private void CreateLibOmvClient()
186 { 226 {
187 GridClient newClient = new GridClient(); 227 GridClient newClient = new GridClient();
@@ -237,16 +277,25 @@ namespace pCampBot
237 private void Action() 277 private void Action()
238 { 278 {
239 while (ConnectionState != ConnectionState.Disconnecting) 279 while (ConnectionState != ConnectionState.Disconnecting)
280 {
240 lock (Behaviours) 281 lock (Behaviours)
241 Behaviours.ForEach( 282 {
242 b => 283 foreach (IBehaviour behaviour in Behaviours.Values)
243 { 284 {
244 Thread.Sleep(Random.Next(3000, 10000)); 285// Thread.Sleep(Random.Next(3000, 10000));
245 286
246 // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType()); 287 // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType());
247 b.Action(); 288 behaviour.Action();
248 } 289 }
249 ); 290 }
291
292 // XXX: This is a really shitty way of yielding so that behaviours can be added/removed
293 Thread.Sleep(100);
294 }
295
296 lock (Behaviours)
297 foreach (IBehaviour b in Behaviours.Values)
298 b.Close();
250 } 299 }
251 300
252 /// <summary> 301 /// <summary>
diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs
index 5c3835b..3c1b11e 100644
--- a/OpenSim/Tools/pCampBot/BotManager.cs
+++ b/OpenSim/Tools/pCampBot/BotManager.cs
@@ -140,7 +140,7 @@ namespace pCampBot
140 /// <summary> 140 /// <summary>
141 /// Behaviour switches for bots. 141 /// Behaviour switches for bots.
142 /// </summary> 142 /// </summary>
143 private HashSet<string> m_behaviourSwitches = new HashSet<string>(); 143 private HashSet<string> m_defaultBehaviourSwitches = new HashSet<string>();
144 144
145 /// <summary> 145 /// <summary>
146 /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data 146 /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data
@@ -195,6 +195,20 @@ namespace pCampBot
195 HandleDisconnect); 195 HandleDisconnect);
196 196
197 m_console.Commands.AddCommand( 197 m_console.Commands.AddCommand(
198 "bot", false, "add behaviour", "add behaviour <abbreviated-name> [<bot-number>]",
199 "Add a behaviour to a bot",
200 "If no bot number is specified then behaviour is added to all bots.\n"
201 + "Can be performed on connected or disconnected bots.",
202 HandleAddBehaviour);
203
204 m_console.Commands.AddCommand(
205 "bot", false, "remove behaviour", "remove behaviour <abbreviated-name> [<bot-number>]",
206 "Remove a behaviour from a bot",
207 "If no bot number is specified then behaviour is added to all bots.\n"
208 + "Can be performed on connected or disconnected bots.",
209 HandleRemoveBehaviour);
210
211 m_console.Commands.AddCommand(
198 "bot", false, "sit", "sit", "Sit all bots on the ground.", 212 "bot", false, "sit", "sit", "Sit all bots on the ground.",
199 HandleSit); 213 HandleSit);
200 214
@@ -212,7 +226,7 @@ namespace pCampBot
212 "bot", false, "show bots", "show bots", "Shows the status of all bots", HandleShowBotsStatus); 226 "bot", false, "show bots", "show bots", "Shows the status of all bots", HandleShowBotsStatus);
213 227
214 m_console.Commands.AddCommand( 228 m_console.Commands.AddCommand(
215 "bot", false, "show bot", "show bot <n>", 229 "bot", false, "show bot", "show bot <bot-number>",
216 "Shows the detailed status and settings of a particular bot.", HandleShowBotStatus); 230 "Shows the detailed status and settings of a particular bot.", HandleShowBotStatus);
217 231
218 m_bots = new List<Bot>(); 232 m_bots = new List<Bot>();
@@ -235,7 +249,7 @@ namespace pCampBot
235 m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last")); 249 m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last"));
236 250
237 Array.ForEach<string>( 251 Array.ForEach<string>(
238 startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_behaviourSwitches.Add(b)); 252 startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_defaultBehaviourSwitches.Add(b));
239 253
240 for (int i = 0; i < botcount; i++) 254 for (int i = 0; i < botcount; i++)
241 { 255 {
@@ -243,28 +257,50 @@ namespace pCampBot
243 { 257 {
244 string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber); 258 string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber);
245 259
246 // We must give each bot its own list of instantiated behaviours since they store state. 260 CreateBot(
247 List<IBehaviour> behaviours = new List<IBehaviour>(); 261 this,
248 262 CreateBehavioursFromAbbreviatedNames(m_defaultBehaviourSwitches),
249 // Hard-coded for now 263 m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
250 if (m_behaviourSwitches.Contains("c")) 264 }
251 behaviours.Add(new CrossBehaviour()); 265 }
266 }
267
268 private List<IBehaviour> CreateBehavioursFromAbbreviatedNames(HashSet<string> abbreviatedNames)
269 {
270 // We must give each bot its own list of instantiated behaviours since they store state.
271 List<IBehaviour> behaviours = new List<IBehaviour>();
272
273 // Hard-coded for now
274 foreach (string abName in abbreviatedNames)
275 {
276 IBehaviour newBehaviour = null;
252 277
253 if (m_behaviourSwitches.Contains("g")) 278 if (abName == "c")
254 behaviours.Add(new GrabbingBehaviour()); 279 newBehaviour = new CrossBehaviour();
255 280
256 if (m_behaviourSwitches.Contains("n")) 281 if (abName == "g")
257 behaviours.Add(new NoneBehaviour()); 282 newBehaviour = new GrabbingBehaviour();
258 283
259 if (m_behaviourSwitches.Contains("p")) 284 if (abName == "n")
260 behaviours.Add(new PhysicsBehaviour()); 285 newBehaviour = new NoneBehaviour();
261
262 if (m_behaviourSwitches.Contains("t"))
263 behaviours.Add(new TeleportBehaviour());
264 286
265 CreateBot(this, behaviours, m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting); 287 if (abName == "p")
288 newBehaviour = new PhysicsBehaviour();
289
290 if (abName == "t")
291 newBehaviour = new TeleportBehaviour();
292
293 if (newBehaviour != null)
294 {
295 behaviours.Add(newBehaviour);
296 }
297 else
298 {
299 MainConsole.Instance.OutputFormat("No behaviour with abbreviated name {0} found", abName);
266 } 300 }
267 } 301 }
302
303 return behaviours;
268 } 304 }
269 305
270 public void ConnectBots(int botcount) 306 public void ConnectBots(int botcount)
@@ -453,6 +489,118 @@ namespace pCampBot
453 } 489 }
454 } 490 }
455 491
492 private void HandleAddBehaviour(string module, string[] cmd)
493 {
494 if (cmd.Length < 3 || cmd.Length > 4)
495 {
496 MainConsole.Instance.OutputFormat("Usage: add behaviour <abbreviated-behaviour> [<bot-number>]");
497 return;
498 }
499
500 string rawBehaviours = cmd[2];
501
502 List<Bot> botsToEffect = new List<Bot>();
503
504 if (cmd.Length == 3)
505 {
506 lock (m_bots)
507 botsToEffect.AddRange(m_bots);
508 }
509 else
510 {
511 int botNumber;
512 if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[3], out botNumber))
513 return;
514
515 Bot bot = GetBotFromNumber(botNumber);
516
517 if (bot == null)
518 {
519 MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
520 return;
521 }
522
523 botsToEffect.Add(bot);
524 }
525
526
527 HashSet<string> rawAbbreviatedSwitchesToAdd = new HashSet<string>();
528 Array.ForEach<string>(rawBehaviours.Split(new char[] { ',' }), b => rawAbbreviatedSwitchesToAdd.Add(b));
529
530 foreach (Bot bot in botsToEffect)
531 {
532 List<IBehaviour> behavioursAdded = new List<IBehaviour>();
533
534 foreach (IBehaviour behaviour in CreateBehavioursFromAbbreviatedNames(rawAbbreviatedSwitchesToAdd))
535 {
536 if (bot.AddBehaviour(behaviour))
537 behavioursAdded.Add(behaviour);
538 }
539
540 MainConsole.Instance.OutputFormat(
541 "Added behaviours {0} to bot {1}",
542 string.Join(", ", behavioursAdded.ConvertAll<string>(b => b.Name).ToArray()), bot.Name);
543 }
544 }
545
546 private void HandleRemoveBehaviour(string module, string[] cmd)
547 {
548 if (cmd.Length < 3 || cmd.Length > 4)
549 {
550 MainConsole.Instance.OutputFormat("Usage: remove behaviour <abbreviated-behaviour> [<bot-number>]");
551 return;
552 }
553
554 string rawBehaviours = cmd[2];
555
556 List<Bot> botsToEffect = new List<Bot>();
557
558 if (cmd.Length == 3)
559 {
560 lock (m_bots)
561 botsToEffect.AddRange(m_bots);
562 }
563 else
564 {
565 int botNumber;
566 if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[3], out botNumber))
567 return;
568
569 Bot bot = GetBotFromNumber(botNumber);
570
571 if (bot == null)
572 {
573 MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
574 return;
575 }
576
577 botsToEffect.Add(bot);
578 }
579
580 HashSet<string> abbreviatedBehavioursToRemove = new HashSet<string>();
581 Array.ForEach<string>(rawBehaviours.Split(new char[] { ',' }), b => abbreviatedBehavioursToRemove.Add(b));
582
583 foreach (Bot bot in botsToEffect)
584 {
585 List<IBehaviour> behavioursRemoved = new List<IBehaviour>();
586
587 foreach (string b in abbreviatedBehavioursToRemove)
588 {
589 IBehaviour behaviour;
590
591 if (bot.TryGetBehaviour(b, out behaviour))
592 {
593 bot.RemoveBehaviour(b);
594 behavioursRemoved.Add(behaviour);
595 }
596 }
597
598 MainConsole.Instance.OutputFormat(
599 "Removed behaviours {0} to bot {1}",
600 string.Join(", ", behavioursRemoved.ConvertAll<string>(b => b.Name).ToArray()), bot.Name);
601 }
602 }
603
456 private void HandleDisconnect(string module, string[] cmd) 604 private void HandleDisconnect(string module, string[] cmd)
457 { 605 {
458 lock (m_bots) 606 lock (m_bots)
@@ -572,10 +720,11 @@ namespace pCampBot
572 private void HandleShowBotsStatus(string module, string[] cmd) 720 private void HandleShowBotsStatus(string module, string[] cmd)
573 { 721 {
574 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 722 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
575 cdt.AddColumn("Name", 30); 723 cdt.AddColumn("Name", 24);
576 cdt.AddColumn("Region", 30); 724 cdt.AddColumn("Region", 24);
577 cdt.AddColumn("Status", 14); 725 cdt.AddColumn("Status", 13);
578 cdt.AddColumn("Connections", 11); 726 cdt.AddColumn("Conns", 5);
727 cdt.AddColumn("Behaviours", 20);
579 728
580 Dictionary<ConnectionState, int> totals = new Dictionary<ConnectionState, int>(); 729 Dictionary<ConnectionState, int> totals = new Dictionary<ConnectionState, int>();
581 foreach (object o in Enum.GetValues(typeof(ConnectionState))) 730 foreach (object o in Enum.GetValues(typeof(ConnectionState)))
@@ -583,13 +732,17 @@ namespace pCampBot
583 732
584 lock (m_bots) 733 lock (m_bots)
585 { 734 {
586 foreach (Bot pb in m_bots) 735 foreach (Bot bot in m_bots)
587 { 736 {
588 Simulator currentSim = pb.Client.Network.CurrentSim; 737 Simulator currentSim = bot.Client.Network.CurrentSim;
589 totals[pb.ConnectionState]++; 738 totals[bot.ConnectionState]++;
590 739
591 cdt.AddRow( 740 cdt.AddRow(
592 pb.Name, currentSim != null ? currentSim.Name : "(none)", pb.ConnectionState, pb.SimulatorsCount); 741 bot.Name,
742 currentSim != null ? currentSim.Name : "(none)",
743 bot.ConnectionState,
744 bot.SimulatorsCount,
745 string.Join(",", bot.Behaviours.Keys.ToArray()));
593 } 746 }
594 } 747 }
595 748
@@ -616,16 +769,11 @@ namespace pCampBot
616 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber)) 769 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber))
617 return; 770 return;
618 771
619 string name = string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber); 772 Bot bot = GetBotFromNumber(botNumber);
620
621 Bot bot;
622
623 lock (m_bots)
624 bot = m_bots.Find(b => b.Name == name);
625 773
626 if (bot == null) 774 if (bot == null)
627 { 775 {
628 MainConsole.Instance.Output("No bot found with name {0}", name); 776 MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
629 return; 777 return;
630 } 778 }
631 779
@@ -645,12 +793,39 @@ namespace pCampBot
645 MainConsole.Instance.Output("Settings"); 793 MainConsole.Instance.Output("Settings");
646 794
647 ConsoleDisplayList statusCdl = new ConsoleDisplayList(); 795 ConsoleDisplayList statusCdl = new ConsoleDisplayList();
796
797 statusCdl.AddRow(
798 "Behaviours",
799 string.Join(", ", bot.Behaviours.Values.ToList().ConvertAll<string>(b => b.Name).ToArray()));
800
648 GridClient botClient = bot.Client; 801 GridClient botClient = bot.Client;
649 statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES); 802 statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES);
650 803
651 MainConsole.Instance.Output(statusCdl.ToString()); 804 MainConsole.Instance.Output(statusCdl.ToString());
652 } 805 }
653 806
807 /// <summary>
808 /// Get a specific bot from its number.
809 /// </summary>
810 /// <returns>null if no bot was found</returns>
811 /// <param name='botNumber'></param>
812 private Bot GetBotFromNumber(int botNumber)
813 {
814 string name = GenerateBotNameFromNumber(botNumber);
815
816 Bot bot;
817
818 lock (m_bots)
819 bot = m_bots.Find(b => b.Name == name);
820
821 return bot;
822 }
823
824 private string GenerateBotNameFromNumber(int botNumber)
825 {
826 return string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber);
827 }
828
654 internal void Grid_GridRegion(object o, GridRegionEventArgs args) 829 internal void Grid_GridRegion(object o, GridRegionEventArgs args)
655 { 830 {
656 lock (RegionsKnown) 831 lock (RegionsKnown)
diff --git a/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs b/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs
index 9c984be..0ed4825 100644
--- a/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs
@@ -32,6 +32,11 @@ namespace pCampBot.Interfaces
32 public interface IBehaviour 32 public interface IBehaviour
33 { 33 {
34 /// <summary> 34 /// <summary>
35 /// Abbreviated name of this behaviour.
36 /// </summary>
37 string AbbreviatedName { get; }
38
39 /// <summary>
35 /// Name of this behaviour. 40 /// Name of this behaviour.
36 /// </summary> 41 /// </summary>
37 string Name { get; } 42 string Name { get; }
@@ -46,6 +51,14 @@ namespace pCampBot.Interfaces
46 void Initialize(Bot bot); 51 void Initialize(Bot bot);
47 52
48 /// <summary> 53 /// <summary>
54 /// Close down this behaviour.
55 /// </summary>
56 /// <remarks>
57 /// This is triggered if a behaviour is removed via explicit command and when a bot is disconnected
58 /// </remarks>
59 void Close();
60
61 /// <summary>
49 /// Action to take when this behaviour is invoked. 62 /// Action to take when this behaviour is invoked.
50 /// </summary> 63 /// </summary>
51 /// <param name="bot"></param> 64 /// <param name="bot"></param>
diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example
index 466aed2..8fe6d0c 100644
--- a/bin/Robust.HG.ini.example
+++ b/bin/Robust.HG.ini.example
@@ -151,7 +151,8 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
151; * 151; *
152[GridService] 152[GridService]
153 LocalServiceModule = "OpenSim.Services.GridService.dll:GridService" 153 LocalServiceModule = "OpenSim.Services.GridService.dll:GridService"
154 HypergridLinker = true 154
155 HypergridLinker = true
155 156
156 ; Realm = "regions" 157 ; Realm = "regions"
157 ; AllowDuplicateNames = "True" 158 ; AllowDuplicateNames = "True"
@@ -168,16 +169,31 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
168 ;; Next, we can specify properties of regions, including default and fallback regions 169 ;; Next, we can specify properties of regions, including default and fallback regions
169 ;; The syntax is: Region_<RegionName> = "<flags>" 170 ;; The syntax is: Region_<RegionName> = "<flags>"
170 ;; or: Region_<RegionID> = "<flags>" 171 ;; or: Region_<RegionID> = "<flags>"
171 ;; where <flags> can be DefaultRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut,Reservation,NoMove,Authenticate 172 ;; where <flags> can be DefaultRegion, DefaultHGRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut, Reservation, NoMove, Authenticate
172 ;; For example: 173 ;;
174 ;; DefaultRegion If a local login cannot be placed in the required region (e.g. home region does not exist, avatar is not allowed entry, etc.)
175 ;; then this region becomes the destination. Only the first online default region will be used. If no DefaultHGRegion
176 ;; is specified then this will also be used as the region for hypergrid connections that require it (commonly because they have not specified
177 ;; an explicit region.
178 ;;
179 ;; DefaultHGRegion If an avatar connecting via the hypergrid does not specify a region, then they are placed here. Only the first online
180 ;; region will be used.
181 ;;
182 ;; FallbackRegion If the DefaultRegion is not available for a local login, then any FallbackRegions are tried instead. These are tried in the
183 ;; order specified. This only applies to local logins at this time, not Hypergrid connections.
184 ;;
185 ;; NoDirectLogin A hypergrid user cannot directly connect to this region. This does not apply to local logins.
186 ;;
187 ;; Persistent When the simulator is shutdown, the region is signalled as offline but left registered on the grid.
188 ;;
173 ; Region_Welcome_Area = "DefaultRegion, FallbackRegion" 189 ; Region_Welcome_Area = "DefaultRegion, FallbackRegion"
174 ; (replace spaces with underscore) 190 ; (replace spaces with underscore)
175 191
176 ;; Allow Hyperlinks to be created at the console 192 ;; Allow Hyperlinks to be created at the console
177 HypergridLinker = true 193 HypergridLinker = true
178 194
179 ;; If you have this set under [Hypergrid], no need to set it here, leave it commented 195 ;; If you have this set under [Hypergrid], no need to set it here, leave it commented
180 ; GatekeeperURI = "http://127.0.0.1:8002" 196 ; GatekeeperURI = "http://127.0.0.1:8002"
181 197
182 198
183; * This is the configuration for the freeswitch server in grid mode 199; * This is the configuration for the freeswitch server in grid mode
diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example
index da1b43a..de6fc28 100644
--- a/bin/Robust.ini.example
+++ b/bin/Robust.ini.example
@@ -132,8 +132,24 @@ MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnecto
132 ;; Next, we can specify properties of regions, including default and fallback regions 132 ;; Next, we can specify properties of regions, including default and fallback regions
133 ;; The syntax is: Region_<RegionName> = "<flags>" 133 ;; The syntax is: Region_<RegionName> = "<flags>"
134 ;; or: Region_<RegionID> = "<flags>" 134 ;; or: Region_<RegionID> = "<flags>"
135 ;; where <flags> can be DefaultRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut,Reservation,NoMove,Authenticate 135 ;; where <flags> can be DefaultRegion, DefaultHGRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut, Reservation, NoMove, Authenticate
136 ;; For example: 136 ;;
137 ;; DefaultRegion If a local login cannot be placed in the required region (e.g. home region does not exist, avatar is not allowed entry, etc.)
138 ;; then this region becomes the destination. Only the first online default region will be used. If no DefaultHGRegion
139 ;; is specified then this will also be used as the region for hypergrid connections that require it (commonly because they have not specified
140 ;; an explicit region.
141 ;;
142 ;; DefaultHGRegion If an avatar connecting via the hypergrid does not specify a region, then they are placed here. Only the first online
143 ;; region will be used.
144 ;;
145 ;; FallbackRegion If the DefaultRegion is not available for a local login, then any FallbackRegions are tried instead. These are tried in the
146 ;; order specified. This only applies to local logins at this time, not Hypergrid connections.
147 ;;
148 ;; NoDirectLogin A hypergrid user cannot directly connect to this region. This does not apply to local logins.
149 ;;
150 ;; Persistent When the simulator is shutdown, the region is signalled as offline but left registered on the grid.
151 ;;
152 ;; Example specification:
137 ; Region_Welcome_Area = "DefaultRegion, FallbackRegion" 153 ; Region_Welcome_Area = "DefaultRegion, FallbackRegion"
138 ; (replace spaces with underscore) 154 ; (replace spaces with underscore)
139 155
diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example
index 6b991a8..f7545d4 100644
--- a/bin/config-include/StandaloneCommon.ini.example
+++ b/bin/config-include/StandaloneCommon.ini.example
@@ -81,11 +81,27 @@
81 ;; Next, we can specify properties of regions, including default and fallback regions 81 ;; Next, we can specify properties of regions, including default and fallback regions
82 ;; The syntax is: Region_<RegioName> = "<flags>" 82 ;; The syntax is: Region_<RegioName> = "<flags>"
83 ;; where <flags> can be DefaultRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut 83 ;; where <flags> can be DefaultRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut
84 ;;
85 ;; DefaultRegion If a local login cannot be placed in the required region (e.g. home region does not exist, avatar is not allowed entry, etc.)
86 ;; then this region becomes the destination. Only the first online default region will be used. If no DefaultHGRegion
87 ;; is specified then this will also be used as the region for hypergrid connections that require it (commonly because they have not specified
88 ;; an explicit region.
89 ;;
90 ;; DefaultHGRegion If an avatar connecting via the hypergrid does not specify a region, then they are placed here. Only the first online
91 ;; region will be used.
92 ;;
93 ;; FallbackRegion If the DefaultRegion is not available for a local login, then any FallbackRegions are tried instead. These are tried in the
94 ;; order specified. This only applies to local logins at this time, not Hypergrid connections.
95 ;;
96 ;; NoDirectLogin A hypergrid user cannot directly connect to this region. This does not apply to local logins.
97 ;;
98 ;; Persistent When the simulator is shutdown, the region is signalled as offline but left registered on the grid.
99 ;;
84 ;; For example: 100 ;; For example:
85 Region_Welcome_Area = "DefaultRegion, FallbackRegion" 101 Region_Welcome_Area = "DefaultRegion, FallbackRegion"
86 102
87 ; === HG ONLY === 103 ; === HG ONLY ===
88 ;; If you have this set under [Hypergrid], no need to set it here, leave it commented 104 ;; If you have this set under [Hypergrid], no need to set it here, leave it commented
89 ; GatekeeperURI="http://127.0.0.1:9000" 105 ; GatekeeperURI="http://127.0.0.1:9000"
90 106
91[LibraryModule] 107[LibraryModule]
@@ -94,7 +110,7 @@
94 110
95[LoginService] 111[LoginService]
96 WelcomeMessage = "Welcome, Avatar!" 112 WelcomeMessage = "Welcome, Avatar!"
97 ;; If you have Gatekeeper set under [Hypergrid], no need to set it here, leave it commented 113 ;; If you have Gatekeeper set under [Hypergrid], no need to set it here, leave it commented
98 ; GatekeeperURI = "http://127.0.0.1:9000" 114 ; GatekeeperURI = "http://127.0.0.1:9000"
99 115
100 SRV_HomeURI = "http://127.0.0.1:9000" 116 SRV_HomeURI = "http://127.0.0.1:9000"