aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs37
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs219
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs196
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs17
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs160
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs41
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs303
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs98
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs220
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs41
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs75
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs289
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs272
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs214
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs71
-rw-r--r--OpenSim/Region/OptionalModules/DataSnapshot/DataRequestHandler.cs (renamed from OpenSim/Region/DataSnapshot/DataRequestHandler.cs)4
-rw-r--r--OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs (renamed from OpenSim/Region/DataSnapshot/DataSnapshotManager.cs)148
-rw-r--r--OpenSim/Region/OptionalModules/DataSnapshot/EstateSnapshot.cs (renamed from OpenSim/Region/DataSnapshot/EstateSnapshot.cs)0
-rw-r--r--OpenSim/Region/OptionalModules/DataSnapshot/Interfaces/IDataSnapshot.cs (renamed from OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshot.cs)0
-rw-r--r--OpenSim/Region/OptionalModules/DataSnapshot/Interfaces/IDataSnapshotProvider.cs (renamed from OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshotProvider.cs)0
-rw-r--r--OpenSim/Region/OptionalModules/DataSnapshot/LLSDDiscovery.cs (renamed from OpenSim/Region/DataSnapshot/LLSDDiscovery.cs)0
-rw-r--r--OpenSim/Region/OptionalModules/DataSnapshot/LandSnapshot.cs (renamed from OpenSim/Region/DataSnapshot/LandSnapshot.cs)0
-rw-r--r--OpenSim/Region/OptionalModules/DataSnapshot/ObjectSnapshot.cs (renamed from OpenSim/Region/DataSnapshot/ObjectSnapshot.cs)0
-rw-r--r--OpenSim/Region/OptionalModules/DataSnapshot/SnapshotStore.cs (renamed from OpenSim/Region/DataSnapshot/SnapshotStore.cs)12
-rw-r--r--OpenSim/Region/OptionalModules/Example/BareBonesNonShared/BareBonesNonSharedModule.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Example/BareBonesShared/BareBonesSharedModule.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs175
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs608
-rwxr-xr-xOpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs21
-rw-r--r--OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs99
-rw-r--r--OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs8
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerClientEventForwarder.cs (renamed from OpenSim/Region/RegionCombinerModule/RegionCombinerClientEventForwarder.cs)0
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs (renamed from OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs)6
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerLargeLandChannel.cs (renamed from OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs)88
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs (renamed from OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs)334
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerPermissionModule.cs (renamed from OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs)2
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionConnections.cs (renamed from OpenSim/Region/RegionCombinerModule/RegionConnections.cs)4
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCourseLocation.cs (renamed from OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs)0
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionData.cs (renamed from OpenSim/Region/RegionCombinerModule/RegionData.cs)1
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs391
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs195
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs200
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs482
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs900
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs19
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs1
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/ActiveConnectionsAJAX.cs (renamed from OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs)84
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/Clients_report.cs (renamed from OpenSim/Region/UserStatistics/Clients_report.cs)27
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/Default_Report.cs (renamed from OpenSim/Region/UserStatistics/Default_Report.cs)27
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/HTMLUtil.cs (renamed from OpenSim/Region/UserStatistics/HTMLUtil.cs)0
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/IStatsReport.cs (renamed from OpenSim/Region/UserStatistics/IStatsReport.cs)1
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/LogLinesAJAX.cs (renamed from OpenSim/Region/UserStatistics/LogLinesAJAX.cs)29
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/Prototype_distributor.cs (renamed from OpenSim/Region/UserStatistics/Prototype_distributor.cs)31
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/Sessions_Report.cs (renamed from OpenSim/Region/UserStatistics/Sessions_Report.cs)5
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/SimStatsAJAX.cs (renamed from OpenSim/Region/UserStatistics/SimStatsAJAX.cs)65
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/Updater_distributor.cs (renamed from OpenSim/Region/UserStatistics/Updater_distributor.cs)4
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs (renamed from OpenSim/Region/UserStatistics/WebStatsModule.cs)30
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/CameraOnlyModeModule.cs176
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/DynamicFloaterModule.cs238
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs304
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/GodNamesModule.cs144
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs171
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/SpecialUIModule.cs165
-rw-r--r--OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs123
-rw-r--r--OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs14
-rw-r--r--OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs34
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs69
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs98
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs154
-rw-r--r--OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs142
-rw-r--r--OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs2
78 files changed, 6723 insertions, 1404 deletions
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 781539a..6fe86b2 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -71,7 +71,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
71 m_client = client; 71 m_client = client;
72 m_scene = scene; 72 m_scene = scene;
73 73
74 Watchdog.StartThread(InternalLoop, "IRCClientView", ThreadPriority.Normal, false, true); 74 WorkManager.StartThread(InternalLoop, "IRCClientView", ThreadPriority.Normal, false, true);
75 } 75 }
76 76
77 private void SendServerCommand(string command) 77 private void SendServerCommand(string command)
@@ -516,7 +516,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
516 516
517 public Vector3 StartPos 517 public Vector3 StartPos
518 { 518 {
519 get { return new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 50); } 519 get { return new Vector3(m_scene.RegionInfo.RegionSizeX * 0.5f, m_scene.RegionInfo.RegionSizeY * 0.5f, 50f); }
520 set { } 520 set { }
521 } 521 }
522 522
@@ -660,6 +660,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
660 public event BakeTerrain OnBakeTerrain; 660 public event BakeTerrain OnBakeTerrain;
661 public event EstateChangeInfo OnEstateChangeInfo; 661 public event EstateChangeInfo OnEstateChangeInfo;
662 public event EstateManageTelehub OnEstateManageTelehub; 662 public event EstateManageTelehub OnEstateManageTelehub;
663 public event CachedTextureRequest OnCachedTextureRequest;
663 public event SetAppearance OnSetAppearance; 664 public event SetAppearance OnSetAppearance;
664 public event AvatarNowWearing OnAvatarNowWearing; 665 public event AvatarNowWearing OnAvatarNowWearing;
665 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; 666 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
@@ -686,6 +687,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
686 public event Action<IClientAPI, bool> OnCompleteMovementToRegion; 687 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
687 public event UpdateAgent OnPreAgentUpdate; 688 public event UpdateAgent OnPreAgentUpdate;
688 public event UpdateAgent OnAgentUpdate; 689 public event UpdateAgent OnAgentUpdate;
690 public event UpdateAgent OnAgentCameraUpdate;
689 public event AgentRequestSit OnAgentRequestSit; 691 public event AgentRequestSit OnAgentRequestSit;
690 public event AgentSit OnAgentSit; 692 public event AgentSit OnAgentSit;
691 public event AvatarPickerRequest OnAvatarPickerRequest; 693 public event AvatarPickerRequest OnAvatarPickerRequest;
@@ -901,12 +903,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
901 903
902 public void Start() 904 public void Start()
903 { 905 {
904 m_scene.AddNewClient(this, PresenceType.User); 906 m_scene.AddNewAgent(this, PresenceType.User);
905 907
906 // Mimicking LLClientView which gets always set appearance from client. 908 // Mimicking LLClientView which gets always set appearance from client.
907 AvatarAppearance appearance; 909 AvatarAppearance appearance;
908 m_scene.GetAvatarAppearance(this, out appearance); 910 m_scene.GetAvatarAppearance(this, out appearance);
909 OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone()); 911 OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone(),appearance.AvatarSize, new WearableCacheItem[0]);
910 } 912 }
911 913
912 public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) 914 public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args)
@@ -938,13 +940,18 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
938 { 940 {
939 941
940 } 942 }
943
944 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
945 {
941 946
947 }
948
942 public void SendStartPingCheck(byte seq) 949 public void SendStartPingCheck(byte seq)
943 { 950 {
944 951
945 } 952 }
946 953
947 public void SendKillObject(ulong regionHandle, List<uint> localID) 954 public void SendKillObject(List<uint> localID)
948 { 955 {
949 956
950 } 957 }
@@ -971,12 +978,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
971 // TODO 978 // TODO
972 } 979 }
973 980
974 public void SendGenericMessage(string method, List<string> message) 981 public void SendGenericMessage(string method, UUID invoice, List<string> message)
975 { 982 {
976 983
977 } 984 }
978 985
979 public void SendGenericMessage(string method, List<byte[]> message) 986 public void SendGenericMessage(string method, UUID invoice, List<byte[]> message)
980 { 987 {
981 988
982 } 989 }
@@ -1050,7 +1057,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1050 { 1057 {
1051 } 1058 }
1052 1059
1053 public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) 1060 public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item)
1054 { 1061 {
1055 1062
1056 } 1063 }
@@ -1190,11 +1197,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1190 1197
1191 } 1198 }
1192 1199
1193 public bool AddMoney(int debit)
1194 {
1195 return true;
1196 }
1197
1198 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition) 1200 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition)
1199 { 1201 {
1200 1202
@@ -1424,9 +1426,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1424 return new byte[0]; 1426 return new byte[0];
1425 } 1427 }
1426 1428
1429#pragma warning disable 0067
1427 public event ViewerEffectEventHandler OnViewerEffect; 1430 public event ViewerEffectEventHandler OnViewerEffect;
1428 public event Action<IClientAPI> OnLogout; 1431 public event Action<IClientAPI> OnLogout;
1429 public event Action<IClientAPI> OnConnectionClosed; 1432 public event Action<IClientAPI> OnConnectionClosed;
1433#pragma warning restore 0067
1430 1434
1431 public void SendBlueBoxMessage(UUID FromAvatarID, string FromAvatarName, string Message) 1435 public void SendBlueBoxMessage(UUID FromAvatarID, string FromAvatarName, string Message)
1432 { 1436 {
@@ -1671,12 +1675,17 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1671 { 1675 {
1672 } 1676 }
1673 1677
1674 public void StopFlying(ISceneEntity presence) 1678 public void SendAgentTerseUpdate(ISceneEntity presence)
1675 { 1679 {
1676 } 1680 }
1677 1681
1678 public void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data) 1682 public void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data)
1679 { 1683 {
1680 } 1684 }
1685
1686 public void SendPartPhysicsProprieties(ISceneEntity entity)
1687 {
1688 }
1689
1681 } 1690 }
1682} 1691}
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
index 9d27386..a1682d2 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
@@ -58,7 +58,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
58 58
59 m_listener.Start(50); 59 m_listener.Start(50);
60 60
61 Watchdog.StartThread(ListenLoop, "IRCServer", ThreadPriority.Normal, false, true); 61 WorkManager.StartThread(ListenLoop, "IRCServer", ThreadPriority.Normal, false, true);
62 m_baseScene = baseScene; 62 m_baseScene = baseScene;
63 } 63 }
64 64
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
index 992f38e..08d0fbf 100644
--- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
30using System.Reflection; 31using System.Reflection;
31using System.Text; 32using System.Text;
32using log4net; 33using log4net;
@@ -51,7 +52,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LindenUDPInfoModule")] 52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LindenUDPInfoModule")]
52 public class LindenUDPInfoModule : ISharedRegionModule 53 public class LindenUDPInfoModule : ISharedRegionModule
53 { 54 {
54// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 56
56 protected Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>(); 57 protected Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
57 58
@@ -130,6 +131,15 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
130 "Go on/off emergency monitoring mode", 131 "Go on/off emergency monitoring mode",
131 "Go on/off emergency monitoring mode", 132 "Go on/off emergency monitoring mode",
132 HandleEmergencyMonitoring); 133 HandleEmergencyMonitoring);
134
135 scene.AddCommand(
136 "Comms", this, "show client stats",
137 "show client stats [first_name last_name]",
138 "Show client request stats",
139 "Without the 'first_name last_name' option, all clients are shown."
140 + " With the 'first_name last_name' option only a specific client is shown.",
141 (mod, cmd) => MainConsole.Instance.Output(HandleClientStatsReport(cmd)));
142
133 } 143 }
134 144
135 public void RemoveRegion(Scene scene) 145 public void RemoveRegion(Scene scene)
@@ -294,7 +304,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
294 private string GetImageQueuesReport(string[] showParams) 304 private string GetImageQueuesReport(string[] showParams)
295 { 305 {
296 if (showParams.Length < 5 || showParams.Length > 6) 306 if (showParams.Length < 5 || showParams.Length > 6)
297 return "Usage: image queues show <first-name> <last-name> [full]"; 307 return "Usage: show image queues <first-name> <last-name> [full]";
298 308
299 string firstName = showParams[3]; 309 string firstName = showParams[3];
300 string lastName = showParams[4]; 310 string lastName = showParams[4];
@@ -385,7 +395,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
385 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); 395 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
386 396
387 report.AppendFormat( 397 report.AppendFormat(
388 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", 398 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7}\n",
389 "Since", 399 "Since",
390 "Pkts", 400 "Pkts",
391 "Pkts", 401 "Pkts",
@@ -397,12 +407,11 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
397 "Q Pkts", 407 "Q Pkts",
398 "Q Pkts", 408 "Q Pkts",
399 "Q Pkts", 409 "Q Pkts",
400 "Q Pkts",
401 "Q Pkts"); 410 "Q Pkts");
402 411
403 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); 412 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", "");
404 report.AppendFormat( 413 report.AppendFormat(
405 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", 414 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7}\n",
406 "Last In", 415 "Last In",
407 "In", 416 "In",
408 "Out", 417 "Out",
@@ -414,8 +423,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
414 "Cloud", 423 "Cloud",
415 "Task", 424 "Task",
416 "Texture", 425 "Texture",
417 "Asset", 426 "Asset");
418 "State");
419 427
420 lock (m_scenes) 428 lock (m_scenes)
421 { 429 {
@@ -424,24 +432,24 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
424 scene.ForEachClient( 432 scene.ForEachClient(
425 delegate(IClientAPI client) 433 delegate(IClientAPI client)
426 { 434 {
427 bool isChild = client.SceneAgent.IsChildAgent;
428 if (isChild && !showChildren)
429 return;
430
431 string name = client.Name;
432 if (pname != "" && name != pname)
433 return;
434
435 string regionName = scene.RegionInfo.RegionName;
436
437 report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
438 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
439 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
440
441 if (client is IStatsCollector) 435 if (client is IStatsCollector)
442 { 436 {
443 IStatsCollector stats = (IStatsCollector)client; 437
438 bool isChild = client.SceneAgent.IsChildAgent;
439 if (isChild && !showChildren)
440 return;
444 441
442 string name = client.Name;
443 if (pname != "" && name != pname)
444 return;
445
446 string regionName = scene.RegionInfo.RegionName;
447
448 report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
449 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
450 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
451
452 IStatsCollector stats = (IStatsCollector)client;
445 report.AppendLine(stats.Report()); 453 report.AppendLine(stats.Report());
446 } 454 }
447 }); 455 });
@@ -479,8 +487,10 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
479 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); 487 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
480 488
481 report.AppendFormat( 489 report.AppendFormat(
482 "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}\n", 490 "{0,8} {1,8} {2,7} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7}\n",
483 "Total", 491 "Max",
492 "Target",
493 "Actual",
484 "Resend", 494 "Resend",
485 "Land", 495 "Land",
486 "Wind", 496 "Wind",
@@ -491,7 +501,9 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
491 501
492 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); 502 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", "");
493 report.AppendFormat( 503 report.AppendFormat(
494 "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", 504 "{0,8} {1,8} {2,7} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7}\n",
505 "kb/s",
506 "kb/s",
495 "kb/s", 507 "kb/s",
496 "kb/s", 508 "kb/s",
497 "kb/s", 509 "kb/s",
@@ -503,8 +515,6 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
503 515
504 report.AppendLine(); 516 report.AppendLine();
505 517
506 bool firstClient = true;
507
508 lock (m_scenes) 518 lock (m_scenes)
509 { 519 {
510 foreach (Scene scene in m_scenes.Values) 520 foreach (Scene scene in m_scenes.Values)
@@ -516,12 +526,6 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
516 { 526 {
517 LLClientView llClient = client as LLClientView; 527 LLClientView llClient = client as LLClientView;
518 528
519 if (firstClient)
520 {
521 report.AppendLine(GetServerThrottlesReport(llClient.UDPServer));
522 firstClient = false;
523 }
524
525 bool isChild = client.SceneAgent.IsChildAgent; 529 bool isChild = client.SceneAgent.IsChildAgent;
526 if (isChild && !showChildren) 530 if (isChild && !showChildren)
527 return; 531 return;
@@ -540,7 +544,11 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
540 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); 544 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
541 545
542 report.AppendFormat( 546 report.AppendFormat(
543 "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", 547 "{0,8} {1,8} {2,7} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7}\n",
548 ci.maxThrottle > 0 ? ((ci.maxThrottle * 8) / 1000).ToString() : "-",
549 llUdpClient.FlowThrottle.AdaptiveEnabled
550 ? ((ci.targetThrottle * 8) / 1000).ToString()
551 : (llUdpClient.FlowThrottle.TotalDripRequest * 8 / 1000).ToString(),
544 (ci.totalThrottle * 8) / 1000, 552 (ci.totalThrottle * 8) / 1000,
545 (ci.resendThrottle * 8) / 1000, 553 (ci.resendThrottle * 8) / 1000,
546 (ci.landThrottle * 8) / 1000, 554 (ci.landThrottle * 8) / 1000,
@@ -548,9 +556,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
548 (ci.cloudThrottle * 8) / 1000, 556 (ci.cloudThrottle * 8) / 1000,
549 (ci.taskThrottle * 8) / 1000, 557 (ci.taskThrottle * 8) / 1000,
550 (ci.textureThrottle * 8) / 1000, 558 (ci.textureThrottle * 8) / 1000,
551 (ci.assetThrottle * 8) / 1000); 559 (ci.assetThrottle * 8) / 1000);
552
553 report.AppendLine();
554 } 560 }
555 }); 561 });
556 } 562 }
@@ -558,35 +564,116 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
558 564
559 return report.ToString(); 565 return report.ToString();
560 } 566 }
561 567
562 protected string GetServerThrottlesReport(LLUDPServer udpServer) 568 /// <summary>
569 /// Show client stats data
570 /// </summary>
571 /// <param name="showParams"></param>
572 /// <returns></returns>
573 protected string HandleClientStatsReport(string[] showParams)
563 { 574 {
564 StringBuilder report = new StringBuilder(); 575 // NOTE: This writes to m_log on purpose. We want to store this information
565 576 // in case we need to analyze it later.
566 int columnPadding = 2; 577 //
567 int maxNameLength = 18; 578 if (showParams.Length <= 4)
568 int maxRegionNameLength = 14; 579 {
569 int maxTypeLength = 4; 580 m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", "Region", "Name", "Root", "Time", "Reqs/min", "AgentUpdates");
570 581 foreach (Scene scene in m_scenes.Values)
571 string name = "SERVER AGENT RATES"; 582 {
572 583 scene.ForEachClient(
573 report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); 584 delegate(IClientAPI client)
574 report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding)); 585 {
575 report.Append(GetColumnEntry("-", maxTypeLength, columnPadding)); 586 if (client is LLClientView)
576 587 {
577 ThrottleRates throttleRates = udpServer.ThrottleRates; 588 LLClientView llClient = client as LLClientView;
578 report.AppendFormat( 589 ClientInfo cinfo = llClient.UDPClient.GetClientInfo();
579 "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", 590 int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
580 (throttleRates.Total * 8) / 1000, 591 avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
581 (throttleRates.Resend * 8) / 1000, 592
582 (throttleRates.Land * 8) / 1000, 593 string childAgentStatus;
583 (throttleRates.Wind * 8) / 1000, 594
584 (throttleRates.Cloud * 8) / 1000, 595 if (llClient.SceneAgent != null)
585 (throttleRates.Task * 8) / 1000, 596 childAgentStatus = llClient.SceneAgent.IsChildAgent ? "N" : "Y";
586 (throttleRates.Texture * 8) / 1000, 597 else
587 (throttleRates.Asset * 8) / 1000); 598 childAgentStatus = "Off!";
599
600 m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}",
601 scene.RegionInfo.RegionName, llClient.Name,
602 childAgentStatus,
603 (DateTime.Now - cinfo.StartedTime).Minutes,
604 avg_reqs,
605 string.Format(
606 "{0} ({1:0.00}%)",
607 llClient.TotalAgentUpdates,
608 cinfo.SyncRequests.ContainsKey("AgentUpdate")
609 ? (float)cinfo.SyncRequests["AgentUpdate"] / llClient.TotalAgentUpdates * 100
610 : 0));
611 }
612 });
613 }
614 return string.Empty;
615 }
588 616
589 return report.ToString(); 617 string fname = "", lname = "";
590 } 618
619 if (showParams.Length > 3)
620 fname = showParams[3];
621 if (showParams.Length > 4)
622 lname = showParams[4];
623
624 foreach (Scene scene in m_scenes.Values)
625 {
626 scene.ForEachClient(
627 delegate(IClientAPI client)
628 {
629 if (client is LLClientView)
630 {
631 LLClientView llClient = client as LLClientView;
632
633 if (llClient.Name == fname + " " + lname)
634 {
635
636 ClientInfo cinfo = llClient.GetClientInfo();
637 AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(llClient.CircuitCode);
638 if (aCircuit == null) // create a dummy one
639 aCircuit = new AgentCircuitData();
640
641 if (!llClient.SceneAgent.IsChildAgent)
642 m_log.InfoFormat("[INFO]: {0} # {1} # {2}", llClient.Name, Util.GetViewerName(aCircuit), aCircuit.Id0);
643
644 int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
645 avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
646
647 m_log.InfoFormat("[INFO]:");
648 m_log.InfoFormat("[INFO]: {0} # {1} # Time: {2}min # Avg Reqs/min: {3}", scene.RegionInfo.RegionName,
649 (llClient.SceneAgent.IsChildAgent ? "Child" : "Root"), (DateTime.Now - cinfo.StartedTime).Minutes, avg_reqs);
650
651 Dictionary<string, int> sortedDict = (from entry in cinfo.AsyncRequests orderby entry.Value descending select entry)
652 .ToDictionary(pair => pair.Key, pair => pair.Value);
653 PrintRequests("TOP ASYNC", sortedDict, cinfo.AsyncRequests.Values.Sum());
654
655 sortedDict = (from entry in cinfo.SyncRequests orderby entry.Value descending select entry)
656 .ToDictionary(pair => pair.Key, pair => pair.Value);
657 PrintRequests("TOP SYNC", sortedDict, cinfo.SyncRequests.Values.Sum());
658
659 sortedDict = (from entry in cinfo.GenericRequests orderby entry.Value descending select entry)
660 .ToDictionary(pair => pair.Key, pair => pair.Value);
661 PrintRequests("TOP GENERIC", sortedDict, cinfo.GenericRequests.Values.Sum());
662 }
663 }
664 });
665 }
666 return string.Empty;
667 }
668
669 private void PrintRequests(string type, Dictionary<string, int> sortedDict, int sum)
670 {
671 m_log.InfoFormat("[INFO]:");
672 m_log.InfoFormat("[INFO]: {0,25}", type);
673 foreach (KeyValuePair<string, int> kvp in sortedDict.Take(12))
674 m_log.InfoFormat("[INFO]: {0,25} {1,-6}", kvp.Key, kvp.Value);
675 m_log.InfoFormat("[INFO]: {0,25}", "...");
676 m_log.InfoFormat("[INFO]: {0,25} {1,-6}", "Total", sum);
677 }
591 } 678 }
592} \ No newline at end of file 679}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
index d718a2f..2f9bb1e 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
@@ -51,7 +51,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
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 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>(); 54 private List<Scene> m_scenes = new List<Scene>();
55
55// private IAvatarFactoryModule m_avatarFactory; 56// private IAvatarFactoryModule m_avatarFactory;
56 57
57 public string Name { get { return "Appearance Information Module"; } } 58 public string Name { get { return "Appearance Information Module"; } }
@@ -83,7 +84,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
83// m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); 84// m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
84 85
85 lock (m_scenes) 86 lock (m_scenes)
86 m_scenes.Remove(scene.RegionInfo.RegionID); 87 m_scenes.Remove(scene);
87 } 88 }
88 89
89 public void RegionLoaded(Scene scene) 90 public void RegionLoaded(Scene scene)
@@ -91,7 +92,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
91// m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); 92// m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
92 93
93 lock (m_scenes) 94 lock (m_scenes)
94 m_scenes[scene.RegionInfo.RegionID] = scene; 95 m_scenes.Add(scene);
95 96
96 scene.AddCommand( 97 scene.AddCommand(
97 "Users", this, "show appearance", 98 "Users", this, "show appearance",
@@ -102,7 +103,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
102 scene.AddCommand( 103 scene.AddCommand(
103 "Users", this, "appearance show", 104 "Users", this, "appearance show",
104 "appearance show [<first-name> <last-name>]", 105 "appearance show [<first-name> <last-name>]",
105 "Show appearance information for each avatar in the simulator.", 106 "Show appearance information for avatars.",
106 "This command checks whether the simulator has all the baked textures required to display an avatar to other viewers. " 107 "This command checks whether the simulator has all the baked textures required to display an avatar to other viewers. "
107 + "\nIf not, then appearance is 'corrupt' and other avatars will continue to see it as a cloud." 108 + "\nIf not, then appearance is 'corrupt' and other avatars will continue to see it as a cloud."
108 + "\nOptionally, you can view just a particular avatar's appearance information." 109 + "\nOptionally, you can view just a particular avatar's appearance information."
@@ -132,6 +133,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
132 "Find out which avatar uses the given asset as a baked texture, if any.", 133 "Find out which avatar uses the given asset as a baked texture, if any.",
133 "You can specify just the beginning of the uuid, e.g. 2008a8d. A longer UUID must be in dashed format.", 134 "You can specify just the beginning of the uuid, e.g. 2008a8d. A longer UUID must be in dashed format.",
134 HandleFindAppearanceCommand); 135 HandleFindAppearanceCommand);
136
137 scene.AddCommand(
138 "Users", this, "wearables show",
139 "wearables show [<first-name> <last-name>]",
140 "Show information about wearables for avatars.",
141 "If no avatar name is given then a general summary for all avatars in the scene is shown.\n"
142 + "If an avatar name is given then specific information about current wearables is shown.",
143 HandleShowWearablesCommand);
144
145 scene.AddCommand(
146 "Users", this, "wearables check",
147 "wearables check <first-name> <last-name>",
148 "Check that the wearables of a given avatar in the scene are valid.",
149 "This currently checks that the wearable assets themselves and any assets referenced by them exist.",
150 HandleCheckWearablesCommand);
135 } 151 }
136 152
137 private void HandleSendAppearanceCommand(string module, string[] cmd) 153 private void HandleSendAppearanceCommand(string module, string[] cmd)
@@ -155,7 +171,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
155 171
156 lock (m_scenes) 172 lock (m_scenes)
157 { 173 {
158 foreach (Scene scene in m_scenes.Values) 174 foreach (Scene scene in m_scenes)
159 { 175 {
160 if (targetNameSupplied) 176 if (targetNameSupplied)
161 { 177 {
@@ -186,7 +202,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
186 } 202 }
187 } 203 }
188 204
189 protected void HandleShowAppearanceCommand(string module, string[] cmd) 205 private void HandleShowAppearanceCommand(string module, string[] cmd)
190 { 206 {
191 if (cmd.Length != 2 && cmd.Length < 4) 207 if (cmd.Length != 2 && cmd.Length < 4)
192 { 208 {
@@ -207,7 +223,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
207 223
208 lock (m_scenes) 224 lock (m_scenes)
209 { 225 {
210 foreach (Scene scene in m_scenes.Values) 226 foreach (Scene scene in m_scenes)
211 { 227 {
212 if (targetNameSupplied) 228 if (targetNameSupplied)
213 { 229 {
@@ -222,7 +238,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
222 { 238 {
223 bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp); 239 bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp);
224 MainConsole.Instance.OutputFormat( 240 MainConsole.Instance.OutputFormat(
225 "{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); 241 "{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "incomplete");
226 } 242 }
227 ); 243 );
228 } 244 }
@@ -243,7 +259,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
243 259
244 lock (m_scenes) 260 lock (m_scenes)
245 { 261 {
246 foreach (Scene scene in m_scenes.Values) 262 foreach (Scene scene in m_scenes)
247 { 263 {
248 ScenePresence sp = scene.GetScenePresence(firstname, lastname); 264 ScenePresence sp = scene.GetScenePresence(firstname, lastname);
249 if (sp != null && !sp.IsChildAgent) 265 if (sp != null && !sp.IsChildAgent)
@@ -263,7 +279,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
263 } 279 }
264 } 280 }
265 281
266 protected void HandleFindAppearanceCommand(string module, string[] cmd) 282 private void HandleFindAppearanceCommand(string module, string[] cmd)
267 { 283 {
268 if (cmd.Length != 3) 284 if (cmd.Length != 3)
269 { 285 {
@@ -277,7 +293,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
277 293
278 lock (m_scenes) 294 lock (m_scenes)
279 { 295 {
280 foreach (Scene scene in m_scenes.Values) 296 foreach (Scene scene in m_scenes)
281 { 297 {
282 scene.ForEachRootScenePresence( 298 scene.ForEachRootScenePresence(
283 sp => 299 sp =>
@@ -304,5 +320,163 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
304 string.Join(", ", matchedAvatars.ToList().ConvertAll<string>(sp => sp.Name).ToArray())); 320 string.Join(", ", matchedAvatars.ToList().ConvertAll<string>(sp => sp.Name).ToArray()));
305 } 321 }
306 } 322 }
323
324 protected void HandleShowWearablesCommand(string module, string[] cmd)
325 {
326 if (cmd.Length != 2 && cmd.Length < 4)
327 {
328 MainConsole.Instance.OutputFormat("Usage: wearables show [<first-name> <last-name>]");
329 return;
330 }
331
332 bool targetNameSupplied = false;
333 string optionalTargetFirstName = null;
334 string optionalTargetLastName = null;
335
336 if (cmd.Length >= 4)
337 {
338 targetNameSupplied = true;
339 optionalTargetFirstName = cmd[2];
340 optionalTargetLastName = cmd[3];
341 }
342
343 StringBuilder sb = new StringBuilder();
344
345 if (targetNameSupplied)
346 {
347 lock (m_scenes)
348 {
349 foreach (Scene scene in m_scenes)
350 {
351 ScenePresence sp = scene.GetScenePresence(optionalTargetFirstName, optionalTargetLastName);
352 if (sp != null && !sp.IsChildAgent)
353 AppendWearablesDetailReport(sp, sb);
354 }
355 }
356 }
357 else
358 {
359 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
360 cdt.AddColumn("Name", ConsoleDisplayUtil.UserNameSize);
361 cdt.AddColumn("Wearables", 2);
362
363 lock (m_scenes)
364 {
365 foreach (Scene scene in m_scenes)
366 {
367 scene.ForEachRootScenePresence(
368 sp =>
369 {
370 int count = 0;
371
372 for (int i = (int)WearableType.Shape; i < (int)WearableType.Physics; i++)
373 count += sp.Appearance.Wearables[i].Count;
374
375 cdt.AddRow(sp.Name, count);
376 }
377 );
378 }
379 }
380
381 sb.Append(cdt.ToString());
382 }
383
384 MainConsole.Instance.Output(sb.ToString());
385 }
386
387 private void HandleCheckWearablesCommand(string module, string[] cmd)
388 {
389 if (cmd.Length != 4)
390 {
391 MainConsole.Instance.OutputFormat("Usage: wearables check <first-name> <last-name>");
392 return;
393 }
394
395 string firstname = cmd[2];
396 string lastname = cmd[3];
397
398 StringBuilder sb = new StringBuilder();
399 UuidGatherer uuidGatherer = new UuidGatherer(m_scenes[0].AssetService);
400
401 lock (m_scenes)
402 {
403 foreach (Scene scene in m_scenes)
404 {
405 ScenePresence sp = scene.GetScenePresence(firstname, lastname);
406 if (sp != null && !sp.IsChildAgent)
407 {
408 sb.AppendFormat("Wearables checks for {0}\n\n", sp.Name);
409
410 for (int i = (int)WearableType.Shape; i < (int)WearableType.Physics; i++)
411 {
412 AvatarWearable aw = sp.Appearance.Wearables[i];
413
414 if (aw.Count > 0)
415 {
416 sb.Append(Enum.GetName(typeof(WearableType), i));
417 sb.Append("\n");
418
419 for (int j = 0; j < aw.Count; j++)
420 {
421 WearableItem wi = aw[j];
422
423 ConsoleDisplayList cdl = new ConsoleDisplayList();
424 cdl.Indent = 2;
425 cdl.AddRow("Item UUID", wi.ItemID);
426 cdl.AddRow("Assets", "");
427 sb.Append(cdl.ToString());
428
429 uuidGatherer.AddForInspection(wi.AssetID);
430 uuidGatherer.GatherAll();
431 string[] assetStrings
432 = Array.ConvertAll<UUID, string>(uuidGatherer.GatheredUuids.Keys.ToArray(), u => u.ToString());
433
434 bool[] existChecks = scene.AssetService.AssetsExist(assetStrings);
435
436 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
437 cdt.Indent = 4;
438 cdt.AddColumn("Type", 10);
439 cdt.AddColumn("UUID", ConsoleDisplayUtil.UuidSize);
440 cdt.AddColumn("Found", 5);
441
442 for (int k = 0; k < existChecks.Length; k++)
443 cdt.AddRow(
444 (AssetType)uuidGatherer.GatheredUuids[new UUID(assetStrings[k])],
445 assetStrings[k], existChecks[k] ? "yes" : "no");
446
447 sb.Append(cdt.ToString());
448 sb.Append("\n");
449 }
450 }
451 }
452 }
453 }
454 }
455
456 MainConsole.Instance.Output(sb.ToString());
457 }
458
459 private void AppendWearablesDetailReport(ScenePresence sp, StringBuilder sb)
460 {
461 sb.AppendFormat("\nWearables for {0}\n", sp.Name);
462
463 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
464 cdt.AddColumn("Type", 10);
465 cdt.AddColumn("Item UUID", ConsoleDisplayUtil.UuidSize);
466 cdt.AddColumn("Asset UUID", ConsoleDisplayUtil.UuidSize);
467
468 for (int i = (int)WearableType.Shape; i < (int)WearableType.Physics; i++)
469 {
470 AvatarWearable aw = sp.Appearance.Wearables[i];
471
472 for (int j = 0; j < aw.Count; j++)
473 {
474 WearableItem wi = aw[j];
475 cdt.AddRow(Enum.GetName(typeof(WearableType), i), wi.ItemID, wi.AssetID);
476 }
477 }
478
479 sb.Append(cdt.ToString());
480 }
307 } 481 }
308} \ No newline at end of file 482} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
index d97e3b3..0333747 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
@@ -176,16 +176,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
176// " {0,-36} {1,-10} {2,-36} {3,-14} {4,-15}\n", 176// " {0,-36} {1,-10} {2,-36} {3,-14} {4,-15}\n",
177// attachmentObject.Name, attachmentObject.LocalId, attachmentObject.FromItemID, 177// attachmentObject.Name, attachmentObject.LocalId, attachmentObject.FromItemID,
178// (AttachmentPoint)attachmentObject.AttachmentPoint, attachmentObject.RootPart.AttachedPos); 178// (AttachmentPoint)attachmentObject.AttachmentPoint, attachmentObject.RootPart.AttachedPos);
179 ct.Rows.Add( 179
180 new ConsoleDisplayTableRow( 180 ct.AddRow(
181 new List<string>() 181 attachmentObject.Name,
182 { 182 attachmentObject.LocalId,
183 attachmentObject.Name, 183 attachmentObject.FromItemID,
184 attachmentObject.LocalId.ToString(), 184 ((AttachmentPoint)attachmentObject.AttachmentPoint),
185 attachmentObject.FromItemID.ToString(), 185 attachmentObject.RootPart.AttachedPos);
186 ((AttachmentPoint)attachmentObject.AttachmentPoint).ToString(),
187 attachmentObject.RootPart.AttachedPos.ToString()
188 }));
189// } 186// }
190 } 187 }
191 188
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
index d7fb272..535bf67 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
@@ -40,6 +40,7 @@ using OpenSim.Framework.Monitoring;
40using OpenSim.Region.ClientStack.LindenUDP; 40using OpenSim.Region.ClientStack.LindenUDP;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using PermissionMask = OpenSim.Framework.PermissionMask;
43 44
44namespace OpenSim.Region.OptionalModules.Avatar.Attachments 45namespace OpenSim.Region.OptionalModules.Avatar.Attachments
45{ 46{
@@ -76,7 +77,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
76 77
77 if (m_console != null) 78 if (m_console != null)
78 { 79 {
79 m_console.AddCommand("TempATtachModule", false, "set auto_grant_attach_perms", "set auto_grant_attach_perms true|false", "Allow objects owned by the region owner os estate managers to obtain attach permissions without asking the user", SetAutoGrantAttachPerms); 80 m_console.AddCommand("TempAttachModule", false, "set auto_grant_attach_perms", "set auto_grant_attach_perms true|false", "Allow objects owned by the region owner or estate managers to obtain attach permissions without asking the user", SetAutoGrantAttachPerms);
80 } 81 }
81 } 82 }
82 else 83 else
@@ -183,7 +184,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
183 hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); 184 hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
184 } 185 }
185 186
186 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true) ? 1 : 0; 187 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, false, true) ? 1 : 0;
187 } 188 }
188 } 189 }
189} 190}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
index 66265d8..b5d9fda 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
@@ -55,42 +55,42 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
55 // These are the IRC Connector configurable parameters with hard-wired 55 // These are the IRC Connector configurable parameters with hard-wired
56 // default values (retained for compatability). 56 // default values (retained for compatability).
57 57
58 internal string Server = null; 58 internal string Server = null;
59 internal string Password = null; 59 internal string Password = null;
60 internal string IrcChannel = null; 60 internal string IrcChannel = null;
61 internal string BaseNickname = "OSimBot"; 61 internal string BaseNickname = "OSimBot";
62 internal uint Port = 6667; 62 internal uint Port = 6667;
63 internal string User = null; 63 internal string User = null;
64 64
65 internal bool ClientReporting = true; 65 internal bool ClientReporting = true;
66 internal bool RelayChat = true; 66 internal bool RelayChat = true;
67 internal bool RelayPrivateChannels = false; 67 internal bool RelayPrivateChannels = false;
68 internal int RelayChannel = 1; 68 internal int RelayChannel = 1;
69 internal List<int> ValidInWorldChannels = new List<int>(); 69 internal List<int> ValidInWorldChannels = new List<int>();
70 70
71 // Connector agnostic parameters. These values are NOT shared with the 71 // Connector agnostic parameters. These values are NOT shared with the
72 // connector and do not differentiate at an IRC level 72 // connector and do not differentiate at an IRC level
73 73
74 internal string PrivateMessageFormat = "PRIVMSG {0} :<{2}> {1} {3}"; 74 internal string PrivateMessageFormat = "PRIVMSG {0} :<{2}> {1} {3}";
75 internal string NoticeMessageFormat = "PRIVMSG {0} :<{2}> {3}"; 75 internal string NoticeMessageFormat = "PRIVMSG {0} :<{2}> {3}";
76 internal int RelayChannelOut = -1; 76 internal int RelayChannelOut = -1;
77 internal bool RandomizeNickname = true; 77 internal bool RandomizeNickname = true;
78 internal bool CommandsEnabled = false; 78 internal bool CommandsEnabled = false;
79 internal int CommandChannel = -1; 79 internal int CommandChannel = -1;
80 internal int ConnectDelay = 10; 80 internal int ConnectDelay = 10;
81 internal int PingDelay = 15; 81 internal int PingDelay = 15;
82 internal string DefaultZone = "Sim"; 82 internal string DefaultZone = "Sim";
83 83
84 internal string _accessPassword = String.Empty; 84 internal string _accessPassword = String.Empty;
85 internal Regex AccessPasswordRegex = null; 85 internal Regex AccessPasswordRegex = null;
86 internal List<string> ExcludeList = new List<string>(); 86 internal List<string> ExcludeList = new List<string>();
87 internal string AccessPassword 87 internal string AccessPassword
88 { 88 {
89 get { return _accessPassword; } 89 get { return _accessPassword; }
90 set 90 set
91 { 91 {
92 _accessPassword = value; 92 _accessPassword = value;
93 AccessPasswordRegex = new Regex(String.Format(@"^{0},\s*(?<avatar>[^,]+),\s*(?<message>.+)$", _accessPassword), 93 AccessPasswordRegex = new Regex(String.Format(@"^{0},\s*(?<avatar>[^,]+),\s*(?<message>.+)$", _accessPassword),
94 RegexOptions.Compiled); 94 RegexOptions.Compiled);
95 } 95 }
96 } 96 }
@@ -99,9 +99,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
99 99
100 // IRC connector reference 100 // IRC connector reference
101 101
102 internal IRCConnector irc = null; 102 internal IRCConnector irc = null;
103 103
104 internal int idn = _idk_++; 104 internal int idn = _idk_++;
105 105
106 // List of regions dependent upon this connection 106 // List of regions dependent upon this connection
107 107
@@ -119,29 +119,29 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
119 119
120 internal ChannelState(ChannelState model) 120 internal ChannelState(ChannelState model)
121 { 121 {
122 Server = model.Server; 122 Server = model.Server;
123 Password = model.Password; 123 Password = model.Password;
124 IrcChannel = model.IrcChannel; 124 IrcChannel = model.IrcChannel;
125 Port = model.Port; 125 Port = model.Port;
126 BaseNickname = model.BaseNickname; 126 BaseNickname = model.BaseNickname;
127 RandomizeNickname = model.RandomizeNickname; 127 RandomizeNickname = model.RandomizeNickname;
128 User = model.User; 128 User = model.User;
129 CommandsEnabled = model.CommandsEnabled; 129 CommandsEnabled = model.CommandsEnabled;
130 CommandChannel = model.CommandChannel; 130 CommandChannel = model.CommandChannel;
131 RelayChat = model.RelayChat; 131 RelayChat = model.RelayChat;
132 RelayPrivateChannels = model.RelayPrivateChannels; 132 RelayPrivateChannels = model.RelayPrivateChannels;
133 RelayChannelOut = model.RelayChannelOut; 133 RelayChannelOut = model.RelayChannelOut;
134 RelayChannel = model.RelayChannel; 134 RelayChannel = model.RelayChannel;
135 ValidInWorldChannels = model.ValidInWorldChannels; 135 ValidInWorldChannels = model.ValidInWorldChannels;
136 PrivateMessageFormat = model.PrivateMessageFormat; 136 PrivateMessageFormat = model.PrivateMessageFormat;
137 NoticeMessageFormat = model.NoticeMessageFormat; 137 NoticeMessageFormat = model.NoticeMessageFormat;
138 ClientReporting = model.ClientReporting; 138 ClientReporting = model.ClientReporting;
139 AccessPassword = model.AccessPassword; 139 AccessPassword = model.AccessPassword;
140 DefaultZone = model.DefaultZone; 140 DefaultZone = model.DefaultZone;
141 ConnectDelay = model.ConnectDelay; 141 ConnectDelay = model.ConnectDelay;
142 PingDelay = model.PingDelay; 142 PingDelay = model.PingDelay;
143 } 143 }
144 144
145 // Read the configuration file, performing variable substitution and any 145 // Read the configuration file, performing variable substitution and any
146 // necessary aliasing. See accompanying documentation for how this works. 146 // necessary aliasing. See accompanying documentation for how this works.
147 // If you don't need variables, then this works exactly as before. 147 // If you don't need variables, then this works exactly as before.
@@ -160,54 +160,54 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
160 160
161 m_log.DebugFormat("[IRC-Channel-{0}] Initial request by Region {1} to connect to IRC", cs.idn, rs.Region); 161 m_log.DebugFormat("[IRC-Channel-{0}] Initial request by Region {1} to connect to IRC", cs.idn, rs.Region);
162 162
163 cs.Server = Substitute(rs, config.GetString("server", null)); 163 cs.Server = Substitute(rs, config.GetString("server", null));
164 m_log.DebugFormat("[IRC-Channel-{0}] Server : <{1}>", cs.idn, cs.Server); 164 m_log.DebugFormat("[IRC-Channel-{0}] Server : <{1}>", cs.idn, cs.Server);
165 cs.Password = Substitute(rs, config.GetString("password", null)); 165 cs.Password = Substitute(rs, config.GetString("password", null));
166 // probably not a good idea to put a password in the log file 166 // probably not a good idea to put a password in the log file
167 cs.User = Substitute(rs, config.GetString("user", null)); 167 cs.User = Substitute(rs, config.GetString("user", null));
168 cs.IrcChannel = Substitute(rs, config.GetString("channel", null)); 168 cs.IrcChannel = Substitute(rs, config.GetString("channel", null));
169 m_log.DebugFormat("[IRC-Channel-{0}] IrcChannel : <{1}>", cs.idn, cs.IrcChannel); 169 m_log.DebugFormat("[IRC-Channel-{0}] IrcChannel : <{1}>", cs.idn, cs.IrcChannel);
170 cs.Port = Convert.ToUInt32(Substitute(rs, config.GetString("port", Convert.ToString(cs.Port)))); 170 cs.Port = Convert.ToUInt32(Substitute(rs, config.GetString("port", Convert.ToString(cs.Port))));
171 m_log.DebugFormat("[IRC-Channel-{0}] Port : <{1}>", cs.idn, cs.Port); 171 m_log.DebugFormat("[IRC-Channel-{0}] Port : <{1}>", cs.idn, cs.Port);
172 cs.BaseNickname = Substitute(rs, config.GetString("nick", cs.BaseNickname)); 172 cs.BaseNickname = Substitute(rs, config.GetString("nick", cs.BaseNickname));
173 m_log.DebugFormat("[IRC-Channel-{0}] BaseNickname : <{1}>", cs.idn, cs.BaseNickname); 173 m_log.DebugFormat("[IRC-Channel-{0}] BaseNickname : <{1}>", cs.idn, cs.BaseNickname);
174 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("randomize_nick", Convert.ToString(cs.RandomizeNickname)))); 174 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("randomize_nick", Convert.ToString(cs.RandomizeNickname))));
175 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname); 175 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
176 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("nicknum", Convert.ToString(cs.RandomizeNickname)))); 176 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("nicknum", Convert.ToString(cs.RandomizeNickname))));
177 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname); 177 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
178 cs.User = Substitute(rs, config.GetString("username", cs.User)); 178 cs.User = Substitute(rs, config.GetString("username", cs.User));
179 m_log.DebugFormat("[IRC-Channel-{0}] User : <{1}>", cs.idn, cs.User); 179 m_log.DebugFormat("[IRC-Channel-{0}] User : <{1}>", cs.idn, cs.User);
180 cs.CommandsEnabled = Convert.ToBoolean(Substitute(rs, config.GetString("commands_enabled", Convert.ToString(cs.CommandsEnabled)))); 180 cs.CommandsEnabled = Convert.ToBoolean(Substitute(rs, config.GetString("commands_enabled", Convert.ToString(cs.CommandsEnabled))));
181 m_log.DebugFormat("[IRC-Channel-{0}] CommandsEnabled : <{1}>", cs.idn, cs.CommandsEnabled); 181 m_log.DebugFormat("[IRC-Channel-{0}] CommandsEnabled : <{1}>", cs.idn, cs.CommandsEnabled);
182 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("commandchannel", Convert.ToString(cs.CommandChannel)))); 182 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("commandchannel", Convert.ToString(cs.CommandChannel))));
183 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel); 183 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
184 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("command_channel", Convert.ToString(cs.CommandChannel)))); 184 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("command_channel", Convert.ToString(cs.CommandChannel))));
185 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel); 185 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
186 cs.RelayChat = Convert.ToBoolean(Substitute(rs, config.GetString("relay_chat", Convert.ToString(cs.RelayChat)))); 186 cs.RelayChat = Convert.ToBoolean(Substitute(rs, config.GetString("relay_chat", Convert.ToString(cs.RelayChat))));
187 m_log.DebugFormat("[IRC-Channel-{0}] RelayChat : <{1}>", cs.idn, cs.RelayChat); 187 m_log.DebugFormat("[IRC-Channel-{0}] RelayChat : <{1}>", cs.idn, cs.RelayChat);
188 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("relay_private_channels", Convert.ToString(cs.RelayPrivateChannels)))); 188 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("relay_private_channels", Convert.ToString(cs.RelayPrivateChannels))));
189 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels); 189 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
190 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("useworldcomm", Convert.ToString(cs.RelayPrivateChannels)))); 190 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("useworldcomm", Convert.ToString(cs.RelayPrivateChannels))));
191 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels); 191 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
192 cs.RelayChannelOut = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_out", Convert.ToString(cs.RelayChannelOut)))); 192 cs.RelayChannelOut = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_out", Convert.ToString(cs.RelayChannelOut))));
193 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannelOut : <{1}>", cs.idn, cs.RelayChannelOut); 193 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannelOut : <{1}>", cs.idn, cs.RelayChannelOut);
194 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_in", Convert.ToString(cs.RelayChannel)))); 194 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_in", Convert.ToString(cs.RelayChannel))));
195 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel); 195 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
196 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("inchannel", Convert.ToString(cs.RelayChannel)))); 196 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("inchannel", Convert.ToString(cs.RelayChannel))));
197 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel); 197 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
198 cs.PrivateMessageFormat = Substitute(rs, config.GetString("msgformat", cs.PrivateMessageFormat)); 198 cs.PrivateMessageFormat = Substitute(rs, config.GetString("msgformat", cs.PrivateMessageFormat));
199 m_log.DebugFormat("[IRC-Channel-{0}] PrivateMessageFormat : <{1}>", cs.idn, cs.PrivateMessageFormat); 199 m_log.DebugFormat("[IRC-Channel-{0}] PrivateMessageFormat : <{1}>", cs.idn, cs.PrivateMessageFormat);
200 cs.NoticeMessageFormat = Substitute(rs, config.GetString("noticeformat", cs.NoticeMessageFormat)); 200 cs.NoticeMessageFormat = Substitute(rs, config.GetString("noticeformat", cs.NoticeMessageFormat));
201 m_log.DebugFormat("[IRC-Channel-{0}] NoticeMessageFormat : <{1}>", cs.idn, cs.NoticeMessageFormat); 201 m_log.DebugFormat("[IRC-Channel-{0}] NoticeMessageFormat : <{1}>", cs.idn, cs.NoticeMessageFormat);
202 cs.ClientReporting = Convert.ToInt32(Substitute(rs, config.GetString("verbosity", cs.ClientReporting?"1":"0"))) > 0; 202 cs.ClientReporting = Convert.ToInt32(Substitute(rs, config.GetString("verbosity", cs.ClientReporting ? "1" : "0"))) > 0;
203 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting); 203 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
204 cs.ClientReporting = Convert.ToBoolean(Substitute(rs, config.GetString("report_clients", Convert.ToString(cs.ClientReporting)))); 204 cs.ClientReporting = Convert.ToBoolean(Substitute(rs, config.GetString("report_clients", Convert.ToString(cs.ClientReporting))));
205 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting); 205 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
206 cs.DefaultZone = Substitute(rs, config.GetString("fallback_region", cs.DefaultZone)); 206 cs.DefaultZone = Substitute(rs, config.GetString("fallback_region", cs.DefaultZone));
207 m_log.DebugFormat("[IRC-Channel-{0}] DefaultZone : <{1}>", cs.idn, cs.DefaultZone); 207 m_log.DebugFormat("[IRC-Channel-{0}] DefaultZone : <{1}>", cs.idn, cs.DefaultZone);
208 cs.ConnectDelay = Convert.ToInt32(Substitute(rs, config.GetString("connect_delay", Convert.ToString(cs.ConnectDelay)))); 208 cs.ConnectDelay = Convert.ToInt32(Substitute(rs, config.GetString("connect_delay", Convert.ToString(cs.ConnectDelay))));
209 m_log.DebugFormat("[IRC-Channel-{0}] ConnectDelay : <{1}>", cs.idn, cs.ConnectDelay); 209 m_log.DebugFormat("[IRC-Channel-{0}] ConnectDelay : <{1}>", cs.idn, cs.ConnectDelay);
210 cs.PingDelay = Convert.ToInt32(Substitute(rs, config.GetString("ping_delay", Convert.ToString(cs.PingDelay)))); 210 cs.PingDelay = Convert.ToInt32(Substitute(rs, config.GetString("ping_delay", Convert.ToString(cs.PingDelay))));
211 m_log.DebugFormat("[IRC-Channel-{0}] PingDelay : <{1}>", cs.idn, cs.PingDelay); 211 m_log.DebugFormat("[IRC-Channel-{0}] PingDelay : <{1}>", cs.idn, cs.PingDelay);
212 cs.AccessPassword = Substitute(rs, config.GetString("access_password", cs.AccessPassword)); 212 cs.AccessPassword = Substitute(rs, config.GetString("access_password", cs.AccessPassword));
213 m_log.DebugFormat("[IRC-Channel-{0}] AccessPassword : <{1}>", cs.idn, cs.AccessPassword); 213 m_log.DebugFormat("[IRC-Channel-{0}] AccessPassword : <{1}>", cs.idn, cs.AccessPassword);
@@ -217,7 +217,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
217 { 217 {
218 cs.ExcludeList.Add(name.Trim().ToLower()); 218 cs.ExcludeList.Add(name.Trim().ToLower());
219 } 219 }
220 220
221 // Fail if fundamental information is still missing 221 // Fail if fundamental information is still missing
222 222
223 if (cs.Server == null) 223 if (cs.Server == null)
@@ -306,8 +306,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
306 306
307 IRCBridgeModule.m_channels.Add(cs); 307 IRCBridgeModule.m_channels.Add(cs);
308 308
309 m_log.InfoFormat("[IRC-Channel-{0}] New channel initialized for {1}, nick: {2}, commands {3}, private channels {4}", 309 m_log.InfoFormat("[IRC-Channel-{0}] New channel initialized for {1}, nick: {2}, commands {3}, private channels {4}",
310 cs.idn, rs.Region, cs.DefaultZone, 310 cs.idn, rs.Region, cs.DefaultZone,
311 cs.CommandsEnabled ? "enabled" : "not enabled", 311 cs.CommandsEnabled ? "enabled" : "not enabled",
312 cs.RelayPrivateChannels ? "relayed" : "not relayed"); 312 cs.RelayPrivateChannels ? "relayed" : "not relayed");
313 } 313 }
@@ -417,7 +417,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
417 private bool IsAConnectionMatchFor(ChannelState cs) 417 private bool IsAConnectionMatchFor(ChannelState cs)
418 { 418 {
419 return ( 419 return (
420 Server == cs.Server && 420 Server == cs.Server &&
421 IrcChannel == cs.IrcChannel && 421 IrcChannel == cs.IrcChannel &&
422 Port == cs.Port && 422 Port == cs.Port &&
423 BaseNickname == cs.BaseNickname && 423 BaseNickname == cs.BaseNickname &&
@@ -461,7 +461,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
461 461
462 string result = instr; 462 string result = instr;
463 463
464 if (result == null || result.Length == 0) 464 if (string.IsNullOrEmpty(result))
465 return result; 465 return result;
466 466
467 // Repeatedly scan the string until all possible 467 // Repeatedly scan the string until all possible
@@ -473,27 +473,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
473 { 473 {
474 474
475 string vvar = arg.Match(result).ToString(); 475 string vvar = arg.Match(result).ToString();
476 string var = vvar.Substring(1,vvar.Length-2).Trim(); 476 string var = vvar.Substring(1, vvar.Length - 2).Trim();
477 477
478 switch (var.ToLower()) 478 switch (var.ToLower())
479 { 479 {
480 case "%region" : 480 case "%region":
481 result = result.Replace(vvar, rs.Region); 481 result = result.Replace(vvar, rs.Region);
482 break; 482 break;
483 case "%host" : 483 case "%host":
484 result = result.Replace(vvar, rs.Host); 484 result = result.Replace(vvar, rs.Host);
485 break; 485 break;
486 case "%locx" : 486 case "%locx":
487 result = result.Replace(vvar, rs.LocX); 487 result = result.Replace(vvar, rs.LocX);
488 break; 488 break;
489 case "%locy" : 489 case "%locy":
490 result = result.Replace(vvar, rs.LocY); 490 result = result.Replace(vvar, rs.LocY);
491 break; 491 break;
492 case "%k" : 492 case "%k":
493 result = result.Replace(vvar, rs.IDK); 493 result = result.Replace(vvar, rs.IDK);
494 break; 494 break;
495 default : 495 default:
496 result = result.Replace(vvar, rs.config.GetString(var,var)); 496 result = result.Replace(vvar, rs.config.GetString(var, var));
497 break; 497 break;
498 } 498 }
499 // m_log.DebugFormat("[IRC-Channel] Parse[2]: {0}", result); 499 // m_log.DebugFormat("[IRC-Channel] Parse[2]: {0}", result);
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs
index 2e1d03d..351dbfe 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs
@@ -46,18 +46,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 internal static bool m_pluginEnabled = false; 49 internal static bool Enabled = false;
50 internal static IConfig m_config = null; 50 internal static IConfig m_config = null;
51 51
52 internal static List<ChannelState> m_channels = new List<ChannelState>(); 52 internal static List<ChannelState> m_channels = new List<ChannelState>();
53 internal static List<RegionState> m_regions = new List<RegionState>(); 53 internal static List<RegionState> m_regions = new List<RegionState>();
54 54
55 internal static string m_password = String.Empty; 55 internal static string m_password = String.Empty;
56 internal RegionState m_region = null; 56 internal RegionState m_region = null;
57 57
58 #region INonSharedRegionModule Members 58 #region INonSharedRegionModule Members
59 59
60 public Type ReplaceableInterface 60 public Type ReplaceableInterface
61 { 61 {
62 get { return null; } 62 get { return null; }
63 } 63 }
@@ -72,13 +72,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
72 m_config = config.Configs["IRC"]; 72 m_config = config.Configs["IRC"];
73 if (m_config == null) 73 if (m_config == null)
74 { 74 {
75// m_log.InfoFormat("[IRC-Bridge] module not configured"); 75 // m_log.InfoFormat("[IRC-Bridge] module not configured");
76 return; 76 return;
77 } 77 }
78 78
79 if (!m_config.GetBoolean("enabled", false)) 79 if (!m_config.GetBoolean("enabled", false))
80 { 80 {
81// m_log.InfoFormat("[IRC-Bridge] module disabled in configuration"); 81 // m_log.InfoFormat("[IRC-Bridge] module disabled in configuration");
82 return; 82 return;
83 } 83 }
84 84
@@ -87,19 +87,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
87 m_password = config.Configs["RemoteAdmin"].GetString("access_password", m_password); 87 m_password = config.Configs["RemoteAdmin"].GetString("access_password", m_password);
88 } 88 }
89 89
90 m_pluginEnabled = true; 90 Enabled = true;
91 m_log.InfoFormat("[IRC-Bridge]: Module enabled"); 91
92 m_log.InfoFormat("[IRC-Bridge]: Module is enabled");
92 } 93 }
93 94
94 public void AddRegion(Scene scene) 95 public void AddRegion(Scene scene)
95 { 96 {
96 if (m_pluginEnabled) 97 if (Enabled)
97 { 98 {
98 try 99 try
99 { 100 {
100 m_log.InfoFormat("[IRC-Bridge] Connecting region {0}", scene.RegionInfo.RegionName); 101 m_log.InfoFormat("[IRC-Bridge] Connecting region {0}", scene.RegionInfo.RegionName);
102
101 if (!String.IsNullOrEmpty(m_password)) 103 if (!String.IsNullOrEmpty(m_password))
102 MainServer.Instance.AddXmlRPCHandler("irc_admin", XmlRpcAdminMethod, false); 104 MainServer.Instance.AddXmlRPCHandler("irc_admin", XmlRpcAdminMethod, false);
105
103 m_region = new RegionState(scene, m_config); 106 m_region = new RegionState(scene, m_config);
104 lock (m_regions) m_regions.Add(m_region); 107 lock (m_regions) m_regions.Add(m_region);
105 m_region.Open(); 108 m_region.Open();
@@ -123,7 +126,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
123 126
124 public void RemoveRegion(Scene scene) 127 public void RemoveRegion(Scene scene)
125 { 128 {
126 if (!m_pluginEnabled) 129 if (!Enabled)
127 return; 130 return;
128 131
129 if (m_region == null) 132 if (m_region == null)
@@ -150,12 +153,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
150 m_log.Debug("[IRC-Bridge]: XML RPC Admin Entry"); 153 m_log.Debug("[IRC-Bridge]: XML RPC Admin Entry");
151 154
152 XmlRpcResponse response = new XmlRpcResponse(); 155 XmlRpcResponse response = new XmlRpcResponse();
153 Hashtable responseData = new Hashtable(); 156 Hashtable responseData = new Hashtable();
154 157
155 try 158 try
156 { 159 {
157 Hashtable requestData = (Hashtable)request.Params[0]; 160 Hashtable requestData = (Hashtable)request.Params[0];
158 bool found = false; 161 bool found = false;
159 string region = String.Empty; 162 string region = String.Empty;
160 163
161 if (m_password != String.Empty) 164 if (m_password != String.Empty)
@@ -169,18 +172,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
169 if (!requestData.ContainsKey("region")) 172 if (!requestData.ContainsKey("region"))
170 throw new Exception("No region name specified"); 173 throw new Exception("No region name specified");
171 region = (string)requestData["region"]; 174 region = (string)requestData["region"];
172 175
173 foreach (RegionState rs in m_regions) 176 foreach (RegionState rs in m_regions)
174 { 177 {
175 if (rs.Region == region) 178 if (rs.Region == region)
176 { 179 {
177 responseData["server"] = rs.cs.Server; 180 responseData["server"] = rs.cs.Server;
178 responseData["port"] = (int)rs.cs.Port; 181 responseData["port"] = (int)rs.cs.Port;
179 responseData["user"] = rs.cs.User; 182 responseData["user"] = rs.cs.User;
180 responseData["channel"] = rs.cs.IrcChannel; 183 responseData["channel"] = rs.cs.IrcChannel;
181 responseData["enabled"] = rs.cs.irc.Enabled; 184 responseData["enabled"] = rs.cs.irc.Enabled;
182 responseData["connected"] = rs.cs.irc.Connected; 185 responseData["connected"] = rs.cs.irc.Connected;
183 responseData["nickname"] = rs.cs.irc.Nick; 186 responseData["nickname"] = rs.cs.irc.Nick;
184 found = true; 187 found = true;
185 break; 188 break;
186 } 189 }
@@ -195,7 +198,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
195 m_log.ErrorFormat("[IRC-Bridge] XML RPC Admin request failed : {0}", e.Message); 198 m_log.ErrorFormat("[IRC-Bridge] XML RPC Admin request failed : {0}", e.Message);
196 199
197 responseData["success"] = "false"; 200 responseData["success"] = "false";
198 responseData["error"] = e.Message; 201 responseData["error"] = e.Message;
199 } 202 }
200 finally 203 finally
201 { 204 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
index a014798..6985371 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
@@ -52,17 +52,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
52 52
53 // Local constants 53 // Local constants
54 54
55 // This computation is not the real region center if the region is larger than 256.
56 // This computation isn't fixed because there is not a handle back to the region.
55 private static readonly Vector3 CenterOfRegion = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20); 57 private static readonly Vector3 CenterOfRegion = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
56 private static readonly char[] CS_SPACE = { ' ' }; 58 private static readonly char[] CS_SPACE = { ' ' };
57 59
58 private const int WD_INTERVAL = 1000; // base watchdog interval 60 private const int WD_INTERVAL = 1000; // base watchdog interval
59 private static int PING_PERIOD = 15; // WD intervals per PING 61 private static int PING_PERIOD = 15; // WD intervals per PING
60 private static int ICCD_PERIOD = 10; // WD intervals between Connects 62 private static int ICCD_PERIOD = 10; // WD intervals between Connects
61 private static int L_TIMEOUT = 25; // Login time out interval 63 private static int L_TIMEOUT = 25; // Login time out interval
62 64
63 private static int _idk_ = 0; // core connector identifier 65 private static int _idk_ = 0; // core connector identifier
64 private static int _pdk_ = 0; // ping interval counter 66 private static int _pdk_ = 0; // ping interval counter
65 private static int _icc_ = ICCD_PERIOD; // IRC connect counter 67 private static int _icc_ = ICCD_PERIOD; // IRC connect counter
66 68
67 // List of configured connectors 69 // List of configured connectors
68 70
@@ -107,13 +109,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
107 109
108 internal int m_resetk = 0; 110 internal int m_resetk = 0;
109 111
110 // Working threads
111
112 private Thread m_listener = null;
113
114 private Object msyncConnect = new Object(); 112 private Object msyncConnect = new Object();
115 113
116 internal bool m_randomizeNick = true; // add random suffix 114 internal bool m_randomizeNick = true; // add random suffix
117 internal string m_baseNick = null; // base name for randomizing 115 internal string m_baseNick = null; // base name for randomizing
118 internal string m_nick = null; // effective nickname 116 internal string m_nick = null; // effective nickname
119 117
@@ -122,7 +120,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
122 get { return m_nick; } 120 get { return m_nick; }
123 set { m_nick = value; } 121 set { m_nick = value; }
124 } 122 }
125 123
126 private bool m_enabled = false; // connector enablement 124 private bool m_enabled = false; // connector enablement
127 public bool Enabled 125 public bool Enabled
128 { 126 {
@@ -130,8 +128,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
130 } 128 }
131 129
132 private bool m_connected = false; // connection status 130 private bool m_connected = false; // connection status
133 private bool m_pending = false; // login disposition 131 private bool m_pending = false; // login disposition
134 private int m_timeout = L_TIMEOUT; // login timeout counter 132 private int m_timeout = L_TIMEOUT; // login timeout counter
135 public bool Connected 133 public bool Connected
136 { 134 {
137 get { return m_connected; } 135 get { return m_connected; }
@@ -143,9 +141,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
143 get { return m_ircChannel; } 141 get { return m_ircChannel; }
144 set { m_ircChannel = value; } 142 set { m_ircChannel = value; }
145 } 143 }
146 144
147 private uint m_port = 6667; // session port 145 private uint m_port = 6667; // session port
148 public uint Port 146 public uint Port
149 { 147 {
150 get { return m_port; } 148 get { return m_port; }
151 set { m_port = value; } 149 set { m_port = value; }
@@ -172,10 +170,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
172 170
173 // Network interface 171 // Network interface
174 172
175 private TcpClient m_tcp; 173 private TcpClient m_tcp;
176 private NetworkStream m_stream = null; 174 private NetworkStream m_stream = null;
177 private StreamReader m_reader; 175 private StreamReader m_reader;
178 private StreamWriter m_writer; 176 private StreamWriter m_writer;
179 177
180 // Channel characteristic info (if available) 178 // Channel characteristic info (if available)
181 179
@@ -193,26 +191,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
193 191
194 // Prepare network interface 192 // Prepare network interface
195 193
196 m_tcp = null; 194 m_tcp = null;
197 m_writer = null; 195 m_writer = null;
198 m_reader = null; 196 m_reader = null;
199 197
200 // Setup IRC session parameters 198 // Setup IRC session parameters
201 199
202 m_server = cs.Server; 200 m_server = cs.Server;
203 m_password = cs.Password; 201 m_password = cs.Password;
204 m_baseNick = cs.BaseNickname; 202 m_baseNick = cs.BaseNickname;
205 m_randomizeNick = cs.RandomizeNickname; 203 m_randomizeNick = cs.RandomizeNickname;
206 m_ircChannel = cs.IrcChannel; 204 m_ircChannel = cs.IrcChannel;
207 m_port = cs.Port; 205 m_port = cs.Port;
208 m_user = cs.User; 206 m_user = cs.User;
209 207
210 if (m_watchdog == null) 208 if (m_watchdog == null)
211 { 209 {
212 // Non-differentiating 210 // Non-differentiating
213 211
214 ICCD_PERIOD = cs.ConnectDelay; 212 ICCD_PERIOD = cs.ConnectDelay;
215 PING_PERIOD = cs.PingDelay; 213 PING_PERIOD = cs.PingDelay;
216 214
217 // Smaller values are not reasonable 215 // Smaller values are not reasonable
218 216
@@ -235,7 +233,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
235 233
236 if (m_randomizeNick) 234 if (m_randomizeNick)
237 m_nick = m_baseNick + Util.RandomClass.Next(1, 99); 235 m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
238 else 236 else
239 m_nick = m_baseNick; 237 m_nick = m_baseNick;
240 238
241 m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); 239 m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn);
@@ -295,18 +293,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
295 m_nick, m_ircChannel, m_server)); 293 m_nick, m_ircChannel, m_server));
296 m_writer.Flush(); 294 m_writer.Flush();
297 } 295 }
298 catch (Exception) {} 296 catch (Exception) { }
299 297
300 298
301 m_connected = false; 299 m_connected = false;
302 300
303 try { m_writer.Close(); } catch (Exception) {} 301 try { m_writer.Close(); }
304 try { m_reader.Close(); } catch (Exception) {} 302 catch (Exception) { }
305 try { m_stream.Close(); } catch (Exception) {} 303 try { m_reader.Close(); }
306 try { m_tcp.Close(); } catch (Exception) {} 304 catch (Exception) { }
305 try { m_stream.Close(); }
306 catch (Exception) { }
307 try { m_tcp.Close(); }
308 catch (Exception) { }
307 309
308 } 310 }
309 311
310 lock (m_connectors) 312 lock (m_connectors)
311 m_connectors.Remove(this); 313 m_connectors.Remove(this);
312 314
@@ -347,20 +349,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
347 if (m_connected) return; 349 if (m_connected) return;
348 350
349 m_connected = true; 351 m_connected = true;
350 m_pending = true; 352 m_pending = true;
351 m_timeout = L_TIMEOUT; 353 m_timeout = L_TIMEOUT;
352 354
353 m_tcp = new TcpClient(m_server, (int)m_port); 355 m_tcp = new TcpClient(m_server, (int)m_port);
354 m_stream = m_tcp.GetStream(); 356 m_stream = m_tcp.GetStream();
355 m_reader = new StreamReader(m_stream); 357 m_reader = new StreamReader(m_stream);
356 m_writer = new StreamWriter(m_stream); 358 m_writer = new StreamWriter(m_stream);
357 359
358 m_log.InfoFormat("[IRC-Connector-{0}]: Connected to {1}:{2}", idn, m_server, m_port); 360 m_log.InfoFormat("[IRC-Connector-{0}]: Connected to {1}:{2}", idn, m_server, m_port);
359 361
360 m_listener = new Thread(new ThreadStart(ListenerRun)); 362 WorkManager.StartThread(ListenerRun, "IRCConnectionListenerThread", ThreadPriority.Normal, true, false);
361 m_listener.Name = "IRCConnectorListenerThread";
362 m_listener.IsBackground = true;
363 m_listener.Start();
364 363
365 // This is the message order recommended by RFC 2812 364 // This is the message order recommended by RFC 2812
366 if (m_password != null) 365 if (m_password != null)
@@ -418,12 +417,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
418 // the socket and it will disappear of its own accord, once this 417 // the socket and it will disappear of its own accord, once this
419 // processing is completed. 418 // processing is completed.
420 419
421 try { m_writer.Close(); } catch (Exception) {} 420 try { m_writer.Close(); }
422 try { m_reader.Close(); } catch (Exception) {} 421 catch (Exception) { }
423 try { m_tcp.Close(); } catch (Exception) {} 422 try { m_reader.Close(); }
423 catch (Exception) { }
424 try { m_tcp.Close(); }
425 catch (Exception) { }
424 426
425 m_connected = false; 427 m_connected = false;
426 m_pending = false; 428 m_pending = false;
427 m_resetk++; 429 m_resetk++;
428 430
429 } 431 }
@@ -495,27 +497,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
495 { 497 {
496 498
497 string inputLine; 499 string inputLine;
498 int resetk = m_resetk; 500 int resetk = m_resetk;
499 501
500 try 502 try
501 { 503 {
502 while (m_enabled && m_connected) 504 while (m_enabled && m_connected)
503 { 505 {
504
505 if ((inputLine = m_reader.ReadLine()) == null) 506 if ((inputLine = m_reader.ReadLine()) == null)
506 throw new Exception("Listener input socket closed"); 507 throw new Exception("Listener input socket closed");
507 508
509 Watchdog.UpdateThread();
510
508 // m_log.Info("[IRCConnector]: " + inputLine); 511 // m_log.Info("[IRCConnector]: " + inputLine);
509 512
510 if (inputLine.Contains("PRIVMSG")) 513 if (inputLine.Contains("PRIVMSG"))
511 { 514 {
512
513 Dictionary<string, string> data = ExtractMsg(inputLine); 515 Dictionary<string, string> data = ExtractMsg(inputLine);
514 516
515 // Any chat ??? 517 // Any chat ???
516 if (data != null) 518 if (data != null)
517 { 519 {
518
519 OSChatMessage c = new OSChatMessage(); 520 OSChatMessage c = new OSChatMessage();
520 c.Message = data["msg"]; 521 c.Message = data["msg"];
521 c.Type = ChatTypeEnum.Region; 522 c.Type = ChatTypeEnum.Region;
@@ -531,9 +532,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
531 c.Message = String.Format("/me {0}", c.Message.Substring(8, c.Message.Length - 9)); 532 c.Message = String.Format("/me {0}", c.Message.Substring(8, c.Message.Length - 9));
532 533
533 ChannelState.OSChat(this, c, false); 534 ChannelState.OSChat(this, c, false);
534
535 } 535 }
536
537 } 536 }
538 else 537 else
539 { 538 {
@@ -553,9 +552,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
553 552
554 if (m_enabled && (m_resetk == resetk)) 553 if (m_enabled && (m_resetk == resetk))
555 Reconnect(); 554 Reconnect();
555
556 Watchdog.RemoveThread();
556 } 557 }
557 558
558 private Regex RE = new Regex(@":(?<nick>[\w-]*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)", 559 private Regex RE = new Regex(@":(?<nick>[\w-]*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)",
559 RegexOptions.Multiline); 560 RegexOptions.Multiline);
560 561
561 private Dictionary<string, string> ExtractMsg(string input) 562 private Dictionary<string, string> ExtractMsg(string input)
@@ -617,8 +618,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
617 string[] commArgs; 618 string[] commArgs;
618 string c_server = m_server; 619 string c_server = m_server;
619 620
620 string pfx = String.Empty; 621 string pfx = String.Empty;
621 string cmd = String.Empty; 622 string cmd = String.Empty;
622 string parms = String.Empty; 623 string parms = String.Empty;
623 624
624 // ":" indicates that a prefix is present 625 // ":" indicates that a prefix is present
@@ -627,15 +628,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
627 // ":" indicates that the remainder of the 628 // ":" indicates that the remainder of the
628 // line is a single parameter value. 629 // line is a single parameter value.
629 630
630 commArgs = command.Split(CS_SPACE,2); 631 commArgs = command.Split(CS_SPACE, 2);
631 632
632 if (commArgs[0].StartsWith(":")) 633 if (commArgs[0].StartsWith(":"))
633 { 634 {
634 pfx = commArgs[0].Substring(1); 635 pfx = commArgs[0].Substring(1);
635 commArgs = commArgs[1].Split(CS_SPACE,2); 636 commArgs = commArgs[1].Split(CS_SPACE, 2);
636 } 637 }
637 638
638 cmd = commArgs[0]; 639 cmd = commArgs[0];
639 parms = commArgs[1]; 640 parms = commArgs[1];
640 641
641 // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}>", idn, pfx, cmd); 642 // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}>", idn, pfx, cmd);
@@ -646,44 +647,44 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
646 // Messages 001-004 are always sent 647 // Messages 001-004 are always sent
647 // following signon. 648 // following signon.
648 649
649 case "001" : // Welcome ... 650 case "001": // Welcome ...
650 case "002" : // Server information 651 case "002": // Server information
651 case "003" : // Welcome ... 652 case "003": // Welcome ...
652 break; 653 break;
653 case "004" : // Server information 654 case "004": // Server information
654 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); 655 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
655 commArgs = parms.Split(CS_SPACE); 656 commArgs = parms.Split(CS_SPACE);
656 c_server = commArgs[1]; 657 c_server = commArgs[1];
657 m_server = c_server; 658 m_server = c_server;
658 version = commArgs[2]; 659 version = commArgs[2];
659 usermod = commArgs[3]; 660 usermod = commArgs[3];
660 chanmod = commArgs[4]; 661 chanmod = commArgs[4];
661 break; 662 break;
662 case "005" : // Server information 663 case "005": // Server information
663 break; 664 break;
664 case "042" : 665 case "042":
665 case "250" : 666 case "250":
666 case "251" : 667 case "251":
667 case "252" : 668 case "252":
668 case "254" : 669 case "254":
669 case "255" : 670 case "255":
670 case "265" : 671 case "265":
671 case "266" : 672 case "266":
672 case "332" : // Subject 673 case "332": // Subject
673 case "333" : // Subject owner (?) 674 case "333": // Subject owner (?)
674 case "353" : // Name list 675 case "353": // Name list
675 case "366" : // End-of-Name list marker 676 case "366": // End-of-Name list marker
676 case "372" : // MOTD body 677 case "372": // MOTD body
677 case "375" : // MOTD start 678 case "375": // MOTD start
678 // m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); 679 // m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
679 break; 680 break;
680 case "376" : // MOTD end 681 case "376": // MOTD end
681 // m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); 682 // m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
682 motd = true; 683 motd = true;
683 break; 684 break;
684 case "451" : // Not registered 685 case "451": // Not registered
685 break; 686 break;
686 case "433" : // Nickname in use 687 case "433": // Nickname in use
687 // Gen a new name 688 // Gen a new name
688 m_nick = m_baseNick + Util.RandomClass.Next(1, 99); 689 m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
689 m_log.ErrorFormat("[IRC-Connector-{0}]: [{1}] IRC SERVER reports NicknameInUse, trying {2}", idn, cmd, m_nick); 690 m_log.ErrorFormat("[IRC-Connector-{0}]: [{1}] IRC SERVER reports NicknameInUse, trying {2}", idn, cmd, m_nick);
@@ -695,29 +696,29 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
695 m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel)); 696 m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel));
696 m_writer.Flush(); 697 m_writer.Flush();
697 break; 698 break;
698 case "479" : // Bad channel name, etc. This will never work, so disable the connection 699 case "479": // Bad channel name, etc. This will never work, so disable the connection
699 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); 700 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE, 2)[1]);
700 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] Connector disabled", idn, cmd); 701 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] Connector disabled", idn, cmd);
701 m_enabled = false; 702 m_enabled = false;
702 m_connected = false; 703 m_connected = false;
703 m_pending = false; 704 m_pending = false;
704 break; 705 break;
705 case "NOTICE" : 706 case "NOTICE":
706 // m_log.WarnFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); 707 // m_log.WarnFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
707 break; 708 break;
708 case "ERROR" : 709 case "ERROR":
709 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); 710 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE, 2)[1]);
710 if (parms.Contains("reconnect too fast")) 711 if (parms.Contains("reconnect too fast"))
711 ICCD_PERIOD++; 712 ICCD_PERIOD++;
712 m_pending = false; 713 m_pending = false;
713 Reconnect(); 714 Reconnect();
714 break; 715 break;
715 case "PING" : 716 case "PING":
716 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); 717 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
717 m_writer.WriteLine(String.Format("PONG {0}", parms)); 718 m_writer.WriteLine(String.Format("PONG {0}", parms));
718 m_writer.Flush(); 719 m_writer.Flush();
719 break; 720 break;
720 case "PONG" : 721 case "PONG":
721 break; 722 break;
722 case "JOIN": 723 case "JOIN":
723 if (m_pending) 724 if (m_pending)
@@ -748,19 +749,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
748 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); 749 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
749 eventIrcQuit(pfx, cmd, parms); 750 eventIrcQuit(pfx, cmd, parms);
750 break; 751 break;
751 default : 752 default:
752 m_log.DebugFormat("[IRC-Connector-{0}] Command '{1}' ignored, parms = {2}", idn, cmd, parms); 753 m_log.DebugFormat("[IRC-Connector-{0}] Command '{1}' ignored, parms = {2}", idn, cmd, parms);
753 break; 754 break;
754 } 755 }
755 756
756 // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}> complete", idn, pfx, cmd); 757 // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}> complete", idn, pfx, cmd);
757 758
758 } 759 }
759 760
760 public void eventIrcJoin(string prefix, string command, string parms) 761 public void eventIrcJoin(string prefix, string command, string parms)
761 { 762 {
762 string[] args = parms.Split(CS_SPACE,2); 763 string[] args = parms.Split(CS_SPACE, 2);
763 string IrcUser = prefix.Split('!')[0]; 764 string IrcUser = prefix.Split('!')[0];
764 string IrcChannel = args[0]; 765 string IrcChannel = args[0];
765 766
766 if (IrcChannel.StartsWith(":")) 767 if (IrcChannel.StartsWith(":"))
@@ -772,8 +773,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
772 773
773 public void eventIrcPart(string prefix, string command, string parms) 774 public void eventIrcPart(string prefix, string command, string parms)
774 { 775 {
775 string[] args = parms.Split(CS_SPACE,2); 776 string[] args = parms.Split(CS_SPACE, 2);
776 string IrcUser = prefix.Split('!')[0]; 777 string IrcUser = prefix.Split('!')[0];
777 string IrcChannel = args[0]; 778 string IrcChannel = args[0];
778 779
779 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCPart {1}:{2}", idn, m_server, m_ircChannel); 780 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCPart {1}:{2}", idn, m_server, m_ircChannel);
@@ -782,7 +783,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
782 783
783 public void eventIrcMode(string prefix, string command, string parms) 784 public void eventIrcMode(string prefix, string command, string parms)
784 { 785 {
785 string[] args = parms.Split(CS_SPACE,2); 786 string[] args = parms.Split(CS_SPACE, 2);
786 string UserMode = args[1]; 787 string UserMode = args[1];
787 788
788 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCMode {1}:{2}", idn, m_server, m_ircChannel); 789 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCMode {1}:{2}", idn, m_server, m_ircChannel);
@@ -794,7 +795,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
794 795
795 public void eventIrcNickChange(string prefix, string command, string parms) 796 public void eventIrcNickChange(string prefix, string command, string parms)
796 { 797 {
797 string[] args = parms.Split(CS_SPACE,2); 798 string[] args = parms.Split(CS_SPACE, 2);
798 string UserOldNick = prefix.Split('!')[0]; 799 string UserOldNick = prefix.Split('!')[0];
799 string UserNewNick = args[0].Remove(0, 1); 800 string UserNewNick = args[0].Remove(0, 1);
800 801
@@ -804,11 +805,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
804 805
805 public void eventIrcKick(string prefix, string command, string parms) 806 public void eventIrcKick(string prefix, string command, string parms)
806 { 807 {
807 string[] args = parms.Split(CS_SPACE,3); 808 string[] args = parms.Split(CS_SPACE, 3);
808 string UserKicker = prefix.Split('!')[0]; 809 string UserKicker = prefix.Split('!')[0];
809 string IrcChannel = args[0]; 810 string IrcChannel = args[0];
810 string UserKicked = args[1]; 811 string UserKicked = args[1];
811 string KickMessage = args[2]; 812 string KickMessage = args[2];
812 813
813 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCKick {1}:{2}", idn, m_server, m_ircChannel); 814 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCKick {1}:{2}", idn, m_server, m_ircChannel);
814 BroadcastSim(UserKicker, "/me kicks kicks {0} off {1} saying \"{2}\"", UserKicked, IrcChannel, KickMessage); 815 BroadcastSim(UserKicker, "/me kicks kicks {0} off {1} saying \"{2}\"", UserKicked, IrcChannel, KickMessage);
@@ -822,7 +823,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
822 823
823 public void eventIrcQuit(string prefix, string command, string parms) 824 public void eventIrcQuit(string prefix, string command, string parms)
824 { 825 {
825 string IrcUser = prefix.Split('!')[0]; 826 string IrcUser = prefix.Split('!')[0];
826 string QuitMessage = parms; 827 string QuitMessage = parms;
827 828
828 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCQuit {1}:{2}", idn, m_server, m_ircChannel); 829 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCQuit {1}:{2}", idn, m_server, m_ircChannel);
@@ -842,65 +843,65 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
842 843
843 // m_log.InfoFormat("[IRC-Watchdog] Status scan, pdk = {0}, icc = {1}", _pdk_, _icc_); 844 // m_log.InfoFormat("[IRC-Watchdog] Status scan, pdk = {0}, icc = {1}", _pdk_, _icc_);
844 845
845 _pdk_ = (_pdk_+1)%PING_PERIOD; // cycle the ping trigger 846 _pdk_ = (_pdk_ + 1) % PING_PERIOD; // cycle the ping trigger
846 _icc_++; // increment the inter-consecutive-connect-delay counter 847 _icc_++; // increment the inter-consecutive-connect-delay counter
847 848
848 lock (m_connectors) 849 lock (m_connectors)
849 foreach (IRCConnector connector in m_connectors) 850 foreach (IRCConnector connector in m_connectors)
850 { 851 {
851 852
852 // m_log.InfoFormat("[IRC-Watchdog] Scanning {0}", connector); 853 // m_log.InfoFormat("[IRC-Watchdog] Scanning {0}", connector);
853 854
854 if (connector.Enabled) 855 if (connector.Enabled)
855 {
856 if (!connector.Connected)
857 { 856 {
858 try 857 if (!connector.Connected)
859 { 858 {
860 // m_log.DebugFormat("[IRC-Watchdog] Connecting {1}:{2}", connector.idn, connector.m_server, connector.m_ircChannel); 859 try
861 connector.Connect(); 860 {
861 // m_log.DebugFormat("[IRC-Watchdog] Connecting {1}:{2}", connector.idn, connector.m_server, connector.m_ircChannel);
862 connector.Connect();
863 }
864 catch (Exception e)
865 {
866 m_log.ErrorFormat("[IRC-Watchdog] Exception on connector {0}: {1} ", connector.idn, e.Message);
867 }
862 } 868 }
863 catch (Exception e) 869 else
864 { 870 {
865 m_log.ErrorFormat("[IRC-Watchdog] Exception on connector {0}: {1} ", connector.idn, e.Message);
866 }
867 }
868 else
869 {
870 871
871 if (connector.m_pending) 872 if (connector.m_pending)
872 {
873 if (connector.m_timeout == 0)
874 { 873 {
875 m_log.ErrorFormat("[IRC-Watchdog] Login timed-out for connector {0}, reconnecting", connector.idn); 874 if (connector.m_timeout == 0)
876 connector.Reconnect(); 875 {
876 m_log.ErrorFormat("[IRC-Watchdog] Login timed-out for connector {0}, reconnecting", connector.idn);
877 connector.Reconnect();
878 }
879 else
880 connector.m_timeout--;
877 } 881 }
878 else
879 connector.m_timeout--;
880 }
881 882
882 // Being marked connected is not enough to ping. Socket establishment can sometimes take a long 883 // Being marked connected is not enough to ping. Socket establishment can sometimes take a long
883 // time, in which case the watch dog might try to ping the server before the socket has been 884 // time, in which case the watch dog might try to ping the server before the socket has been
884 // set up, with nasty side-effects. 885 // set up, with nasty side-effects.
885 886
886 else if (_pdk_ == 0) 887 else if (_pdk_ == 0)
887 {
888 try
889 {
890 connector.m_writer.WriteLine(String.Format("PING :{0}", connector.m_server));
891 connector.m_writer.Flush();
892 }
893 catch (Exception e)
894 { 888 {
895 m_log.ErrorFormat("[IRC-PingRun] Exception on connector {0}: {1} ", connector.idn, e.Message); 889 try
896 m_log.Debug(e); 890 {
897 connector.Reconnect(); 891 connector.m_writer.WriteLine(String.Format("PING :{0}", connector.m_server));
892 connector.m_writer.Flush();
893 }
894 catch (Exception e)
895 {
896 m_log.ErrorFormat("[IRC-PingRun] Exception on connector {0}: {1} ", connector.idn, e.Message);
897 m_log.Debug(e);
898 connector.Reconnect();
899 }
898 } 900 }
899 }
900 901
902 }
901 } 903 }
902 } 904 }
903 }
904 905
905 // m_log.InfoFormat("[IRC-Watchdog] Status scan completed"); 906 // m_log.InfoFormat("[IRC-Watchdog] Status scan completed");
906 907
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
index 53b103e..5505001 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
@@ -41,49 +41,73 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
41 41
42 internal class RegionState 42 internal class RegionState
43 { 43 {
44
45 private static readonly ILog m_log = 44 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 46
47 // This computation is not the real region center if the region is larger than 256.
48 // This computation isn't fixed because there is not a handle back to the region.
48 private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20); 49 private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
49 private const int DEBUG_CHANNEL = 2147483647; 50 private const int DEBUG_CHANNEL = 2147483647;
50 51
51 private static int _idk_ = 0; 52 private static int _idk_ = 0;
52 53
53 // Runtime variables; these values are assigned when the 54 // Runtime variables; these values are assigned when the
54 // IrcState is created and remain constant thereafter. 55 // IrcState is created and remain constant thereafter.
55 56
56 internal string Region = String.Empty; 57 internal string Region = String.Empty;
57 internal string Host = String.Empty; 58 internal string Host = String.Empty;
58 internal string LocX = String.Empty; 59 internal string LocX = String.Empty;
59 internal string LocY = String.Empty; 60 internal string LocY = String.Empty;
60 internal string IDK = String.Empty; 61 internal string IDK = String.Empty;
61 62
62 // System values - used only be the IRC classes themselves 63 // System values - used only be the IRC classes themselves
63 64
64 internal ChannelState cs = null; // associated IRC configuration 65 internal ChannelState cs = null; // associated IRC configuration
65 internal Scene scene = null; // associated scene 66 internal Scene scene = null; // associated scene
66 internal IConfig config = null; // configuration file reference 67 internal IConfig config = null; // configuration file reference
67 internal bool enabled = true; 68 internal bool enabled = true;
68 69
70 //AgentAlert
71 internal bool showAlert = false;
72 internal string alertMessage = String.Empty;
73 internal IDialogModule dialogModule = null;
74
69 // This list is used to keep track of who is here, and by 75 // This list is used to keep track of who is here, and by
70 // implication, who is not. 76 // implication, who is not.
71 77
72 internal List<IClientAPI> clients = new List<IClientAPI>(); 78 internal List<IClientAPI> clients = new List<IClientAPI>();
73 79
74 // Setup runtime variable values 80 // Setup runtime variable values
75 81
76 public RegionState(Scene p_scene, IConfig p_config) 82 public RegionState(Scene p_scene, IConfig p_config)
77 { 83 {
78 84 scene = p_scene;
79 scene = p_scene;
80 config = p_config; 85 config = p_config;
81 86
82 Region = scene.RegionInfo.RegionName; 87 Region = scene.RegionInfo.RegionName;
83 Host = scene.RegionInfo.ExternalHostName; 88 Host = scene.RegionInfo.ExternalHostName;
84 LocX = Convert.ToString(scene.RegionInfo.RegionLocX); 89 LocX = Convert.ToString(scene.RegionInfo.RegionLocX);
85 LocY = Convert.ToString(scene.RegionInfo.RegionLocY); 90 LocY = Convert.ToString(scene.RegionInfo.RegionLocY);
86 IDK = Convert.ToString(_idk_++); 91 IDK = Convert.ToString(_idk_++);
92
93 showAlert = config.GetBoolean("alert_show", false);
94 string alertServerInfo = String.Empty;
95
96 if (showAlert)
97 {
98 bool showAlertServerInfo = config.GetBoolean("alert_show_serverinfo", true);
99
100 if (showAlertServerInfo)
101 alertServerInfo = String.Format("\nServer: {0}\nPort: {1}\nChannel: {2}\n\n",
102 config.GetString("server", ""), config.GetString("port", ""), config.GetString("channel", ""));
103
104 string alertPreMessage = config.GetString("alert_msg_pre", "This region is linked to Irc.");
105 string alertPostMessage = config.GetString("alert_msg_post", "Everything you say in public chat can be listened.");
106
107 alertMessage = String.Format("{0}\n{1}{2}", alertPreMessage, alertServerInfo, alertPostMessage);
108
109 dialogModule = scene.RequestModuleInterface<IDialogModule>();
110 }
87 111
88 // OpenChannel conditionally establishes a connection to the 112 // OpenChannel conditionally establishes a connection to the
89 // IRC server. The request will either succeed, or it will 113 // IRC server. The request will either succeed, or it will
@@ -93,9 +117,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
93 117
94 // Connect channel to world events 118 // Connect channel to world events
95 119
96 scene.EventManager.OnChatFromWorld += OnSimChat; 120 scene.EventManager.OnChatFromWorld += OnSimChat;
97 scene.EventManager.OnChatFromClient += OnSimChat; 121 scene.EventManager.OnChatFromClient += OnSimChat;
98 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; 122 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
99 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; 123 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
100 124
101 m_log.InfoFormat("[IRC-Region {0}] Initialization complete", Region); 125 m_log.InfoFormat("[IRC-Region {0}] Initialization complete", Region);
@@ -106,8 +130,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
106 130
107 ~RegionState() 131 ~RegionState()
108 { 132 {
109 if (cs != null) 133 if (cs != null)
110 cs.RemoveRegion(this); 134 cs.RemoveRegion(this);
111 } 135 }
112 136
113 // Called by PostInitialize after all regions have been created 137 // Called by PostInitialize after all regions have been created
@@ -138,7 +162,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
138 { 162 {
139 if (clients.Contains(client)) 163 if (clients.Contains(client))
140 { 164 {
141 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) 165 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting))
142 { 166 {
143 m_log.InfoFormat("[IRC-Region {0}]: {1} has left", Region, client.Name); 167 m_log.InfoFormat("[IRC-Region {0}]: {1} has left", Region, client.Name);
144 //Check if this person is excluded from IRC 168 //Check if this person is excluded from IRC
@@ -147,7 +171,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
147 cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", client.Name)); 171 cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", client.Name));
148 } 172 }
149 } 173 }
150 client.OnLogout -= OnClientLoggedOut; 174 client.OnLogout -= OnClientLoggedOut;
151 client.OnConnectionClosed -= OnClientLoggedOut; 175 client.OnConnectionClosed -= OnClientLoggedOut;
152 clients.Remove(client); 176 clients.Remove(client);
153 } 177 }
@@ -171,13 +195,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
171 { 195 {
172 if (clients.Contains(client)) 196 if (clients.Contains(client))
173 { 197 {
174 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) 198 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting))
175 { 199 {
176 string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname); 200 string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname);
177 m_log.DebugFormat("[IRC-Region {0}] {1} has left", Region, clientName); 201 m_log.DebugFormat("[IRC-Region {0}] {1} has left", Region, clientName);
178 cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", clientName)); 202 cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", clientName));
179 } 203 }
180 client.OnLogout -= OnClientLoggedOut; 204 client.OnLogout -= OnClientLoggedOut;
181 client.OnConnectionClosed -= OnClientLoggedOut; 205 client.OnConnectionClosed -= OnClientLoggedOut;
182 clients.Remove(client); 206 clients.Remove(client);
183 } 207 }
@@ -195,14 +219,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
195 219
196 private void OnMakeRootAgent(ScenePresence presence) 220 private void OnMakeRootAgent(ScenePresence presence)
197 { 221 {
198
199 IClientAPI client = presence.ControllingClient; 222 IClientAPI client = presence.ControllingClient;
200 223
201 try 224 try
202 { 225 {
203 if (!clients.Contains(client)) 226 if (!clients.Contains(client))
204 { 227 {
205 client.OnLogout += OnClientLoggedOut; 228 client.OnLogout += OnClientLoggedOut;
206 client.OnConnectionClosed += OnClientLoggedOut; 229 client.OnConnectionClosed += OnClientLoggedOut;
207 clients.Add(client); 230 clients.Add(client);
208 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) 231 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting))
@@ -216,17 +239,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
216 } 239 }
217 } 240 }
218 } 241 }
242
243 if (dialogModule != null && showAlert)
244 dialogModule.SendAlertToUser(client, alertMessage, true);
219 } 245 }
220 catch (Exception ex) 246 catch (Exception ex)
221 { 247 {
222 m_log.ErrorFormat("[IRC-Region {0}]: MakeRootAgent exception: {1}", Region, ex.Message); 248 m_log.ErrorFormat("[IRC-Region {0}]: MakeRootAgent exception: {1}", Region, ex.Message);
223 m_log.Debug(ex); 249 m_log.Debug(ex);
224 } 250 }
225
226 } 251 }
227 252
228 // This handler detects chat events int he virtual world. 253 // This handler detects chat events int he virtual world.
229
230 public void OnSimChat(Object sender, OSChatMessage msg) 254 public void OnSimChat(Object sender, OSChatMessage msg)
231 { 255 {
232 256
@@ -317,14 +341,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
317 // that evident. 341 // that evident.
318 342
319 default: 343 default:
320 m_log.DebugFormat("[IRC-Region {0}] Forwarding unrecognized command to IRC : {1}", 344 m_log.DebugFormat("[IRC-Region {0}] Forwarding unrecognized command to IRC : {1}",
321 Region, msg.Message); 345 Region, msg.Message);
322 cs.irc.Send(msg.Message); 346 cs.irc.Send(msg.Message);
323 break; 347 break;
324 } 348 }
325 } 349 }
326 catch (Exception ex) 350 catch (Exception ex)
327 { 351 {
328 m_log.WarnFormat("[IRC-Region {0}] error processing in-world command channel input: {1}", 352 m_log.WarnFormat("[IRC-Region {0}] error processing in-world command channel input: {1}",
329 Region, ex.Message); 353 Region, ex.Message);
330 m_log.Debug(ex); 354 m_log.Debug(ex);
@@ -366,7 +390,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
366 390
367 m_log.DebugFormat("[IRC-Region {0}] heard on channel {1} : {2}", Region, msg.Channel, msg.Message); 391 m_log.DebugFormat("[IRC-Region {0}] heard on channel {1} : {2}", Region, msg.Channel, msg.Message);
368 392
369 if (null != avatar && cs.RelayChat && (msg.Channel == 0 || msg.Channel == DEBUG_CHANNEL)) 393 if (null != avatar && cs.RelayChat && (msg.Channel == 0 || msg.Channel == DEBUG_CHANNEL))
370 { 394 {
371 string txt = msg.Message; 395 string txt = msg.Message;
372 if (txt.StartsWith("/me ")) 396 if (txt.StartsWith("/me "))
@@ -376,13 +400,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
376 return; 400 return;
377 } 401 }
378 402
379 if (null == avatar && cs.RelayPrivateChannels && null != cs.AccessPassword && 403 if (null == avatar && cs.RelayPrivateChannels && null != cs.AccessPassword &&
380 msg.Channel == cs.RelayChannelOut) 404 msg.Channel == cs.RelayChannelOut)
381 { 405 {
382 Match m = cs.AccessPasswordRegex.Match(msg.Message); 406 Match m = cs.AccessPasswordRegex.Match(msg.Message);
383 if (null != m) 407 if (null != m)
384 { 408 {
385 m_log.DebugFormat("[IRC] relaying message from {0}: {1}", m.Groups["avatar"].ToString(), 409 m_log.DebugFormat("[IRC] relaying message from {0}: {1}", m.Groups["avatar"].ToString(),
386 m.Groups["message"].ToString()); 410 m.Groups["message"].ToString());
387 cs.irc.PrivMsg(cs.PrivateMessageFormat, m.Groups["avatar"].ToString(), 411 cs.irc.PrivMsg(cs.PrivateMessageFormat, m.Groups["avatar"].ToString(),
388 scene.RegionInfo.RegionName, m.Groups["message"].ToString()); 412 scene.RegionInfo.RegionName, m.Groups["message"].ToString());
diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
index 018357a..c48e585 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
@@ -375,11 +375,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge
375 scene.GetRootAgentCount(), scene.RegionInfo.RegionName, 375 scene.GetRootAgentCount(), scene.RegionInfo.RegionName,
376 scene.RegionInfo.RegionID, 376 scene.RegionInfo.RegionID,
377 DateTime.UtcNow.ToString("s"))); 377 DateTime.UtcNow.ToString("s")));
378
378 scene.ForEachRootScenePresence(delegate(ScenePresence sp) 379 scene.ForEachRootScenePresence(delegate(ScenePresence sp)
379 { 380 {
380 list.Append(String.Format(" <avatar name=\"{0}\" uuid=\"{1}\" />\n", sp.Name, sp.UUID)); 381 list.Append(String.Format(" <avatar name=\"{0}\" uuid=\"{1}\" />\n", sp.Name, sp.UUID));
381 list.Append("</avatars>");
382 }); 382 });
383
384 list.Append("</avatars>");
383 string payload = list.ToString(); 385 string payload = list.ToString();
384 386
385 // post via REST to broker 387 // post via REST to broker
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/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index 37ab35a..45af212 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -65,7 +65,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
65 // Capability string prefixes 65 // Capability string prefixes
66 private static readonly string m_parcelVoiceInfoRequestPath = "0207/"; 66 private static readonly string m_parcelVoiceInfoRequestPath = "0207/";
67 private static readonly string m_provisionVoiceAccountRequestPath = "0208/"; 67 private static readonly string m_provisionVoiceAccountRequestPath = "0208/";
68 private static readonly string m_chatSessionRequestPath = "0209/"; 68 //private static readonly string m_chatSessionRequestPath = "0209/";
69 69
70 // Control info 70 // Control info
71 private static bool m_Enabled = false; 71 private static bool m_Enabled = false;
@@ -326,15 +326,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
326 "ParcelVoiceInfoRequest", 326 "ParcelVoiceInfoRequest",
327 agentID.ToString())); 327 agentID.ToString()));
328 328
329 caps.RegisterHandler( 329 //caps.RegisterHandler(
330 "ChatSessionRequest", 330 // "ChatSessionRequest",
331 new RestStreamHandler( 331 // new RestStreamHandler(
332 "POST", 332 // "POST",
333 capsBase + m_chatSessionRequestPath, 333 // capsBase + m_chatSessionRequestPath,
334 (request, path, param, httpRequest, httpResponse) 334 // (request, path, param, httpRequest, httpResponse)
335 => ChatSessionRequest(scene, request, path, param, agentID, caps), 335 // => ChatSessionRequest(scene, request, path, param, agentID, caps),
336 "ChatSessionRequest", 336 // "ChatSessionRequest",
337 agentID.ToString())); 337 // agentID.ToString()));
338 } 338 }
339 339
340 /// <summary> 340 /// <summary>
@@ -551,13 +551,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
551 reqStream.Close(); 551 reqStream.Close();
552 } 552 }
553 553
554 HttpWebResponse fwdrsp = (HttpWebResponse)forwardreq.GetResponse(); 554 using (HttpWebResponse fwdrsp = (HttpWebResponse)forwardreq.GetResponse())
555 Encoding encoding = Util.UTF8; 555 {
556 StreamReader fwdresponsestream = new StreamReader(fwdrsp.GetResponseStream(), encoding); 556 Encoding encoding = Util.UTF8;
557 fwdresponsestr = fwdresponsestream.ReadToEnd(); 557
558 fwdresponsecontenttype = fwdrsp.ContentType; 558 using (Stream s = fwdrsp.GetResponseStream())
559 fwdresponsecode = (int)fwdrsp.StatusCode; 559 {
560 fwdresponsestream.Close(); 560 using (StreamReader fwdresponsestream = new StreamReader(s))
561 {
562 fwdresponsestr = fwdresponsestream.ReadToEnd();
563 fwdresponsecontenttype = fwdrsp.ContentType;
564 fwdresponsecode = (int)fwdrsp.StatusCode;
565 }
566 }
567 }
561 568
562 response["content_type"] = fwdresponsecontenttype; 569 response["content_type"] = fwdresponsecontenttype;
563 response["str_response_string"] = fwdresponsestr; 570 response["str_response_string"] = fwdresponsestr;
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index 881807a..dd44564 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
92 // Capability strings 92 // Capability strings
93 private static readonly string m_parcelVoiceInfoRequestPath = "0107/"; 93 private static readonly string m_parcelVoiceInfoRequestPath = "0107/";
94 private static readonly string m_provisionVoiceAccountRequestPath = "0108/"; 94 private static readonly string m_provisionVoiceAccountRequestPath = "0108/";
95 private static readonly string m_chatSessionRequestPath = "0109/"; 95 //private static readonly string m_chatSessionRequestPath = "0109/";
96 96
97 // Control info, e.g. vivox server, admin user, admin password 97 // Control info, e.g. vivox server, admin user, admin password
98 private static bool m_pluginEnabled = false; 98 private static bool m_pluginEnabled = false;
@@ -117,6 +117,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
117 117
118 private IConfig m_config; 118 private IConfig m_config;
119 119
120 private object m_Lock;
121
120 public void Initialise(IConfigSource config) 122 public void Initialise(IConfigSource config)
121 { 123 {
122 124
@@ -128,6 +130,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
128 if (!m_config.GetBoolean("enabled", false)) 130 if (!m_config.GetBoolean("enabled", false))
129 return; 131 return;
130 132
133 m_Lock = new object();
134
131 try 135 try
132 { 136 {
133 // retrieve configuration variables 137 // retrieve configuration variables
@@ -429,15 +433,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
429 "ParcelVoiceInfoRequest", 433 "ParcelVoiceInfoRequest",
430 agentID.ToString())); 434 agentID.ToString()));
431 435
432 caps.RegisterHandler( 436 //caps.RegisterHandler(
433 "ChatSessionRequest", 437 // "ChatSessionRequest",
434 new RestStreamHandler( 438 // new RestStreamHandler(
435 "POST", 439 // "POST",
436 capsBase + m_chatSessionRequestPath, 440 // capsBase + m_chatSessionRequestPath,
437 (request, path, param, httpRequest, httpResponse) 441 // (request, path, param, httpRequest, httpResponse)
438 => ChatSessionRequest(scene, request, path, param, agentID, caps), 442 // => ChatSessionRequest(scene, request, path, param, agentID, caps),
439 "ChatSessionRequest", 443 // "ChatSessionRequest",
440 agentID.ToString())); 444 // agentID.ToString()));
441 } 445 }
442 446
443 /// <summary> 447 /// <summary>
@@ -818,11 +822,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
818 { 822 {
819 string requrl = String.Format(m_vivoxChannelPath, m_vivoxServer, "create", channelId, m_authToken); 823 string requrl = String.Format(m_vivoxChannelPath, m_vivoxServer, "create", channelId, m_authToken);
820 824
821 if (parent != null && parent != String.Empty) 825 if (!string.IsNullOrEmpty(parent))
822 { 826 {
823 requrl = String.Format("{0}&chan_parent={1}", requrl, parent); 827 requrl = String.Format("{0}&chan_parent={1}", requrl, parent);
824 } 828 }
825 if (description != null && description != String.Empty) 829 if (!string.IsNullOrEmpty(description))
826 { 830 {
827 requrl = String.Format("{0}&chan_desc={1}", requrl, description); 831 requrl = String.Format("{0}&chan_desc={1}", requrl, description);
828 } 832 }
@@ -832,7 +836,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
832 requrl = String.Format("{0}&chan_roll_off={1}", requrl, m_vivoxChannelRollOff); 836 requrl = String.Format("{0}&chan_roll_off={1}", requrl, m_vivoxChannelRollOff);
833 requrl = String.Format("{0}&chan_dist_model={1}", requrl, m_vivoxChannelDistanceModel); 837 requrl = String.Format("{0}&chan_dist_model={1}", requrl, m_vivoxChannelDistanceModel);
834 requrl = String.Format("{0}&chan_max_range={1}", requrl, m_vivoxChannelMaximumRange); 838 requrl = String.Format("{0}&chan_max_range={1}", requrl, m_vivoxChannelMaximumRange);
835 requrl = String.Format("{0}&chan_ckamping_distance={1}", requrl, m_vivoxChannelClampingDistance); 839 requrl = String.Format("{0}&chan_clamping_distance={1}", requrl, m_vivoxChannelClampingDistance);
836 840
837 XmlElement resp = VivoxCall(requrl, true); 841 XmlElement resp = VivoxCall(requrl, true);
838 if (XmlFind(resp, "response.level0.body.chan_uri", out channelUri)) 842 if (XmlFind(resp, "response.level0.body.chan_uri", out channelUri))
@@ -858,7 +862,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
858 // requrl = String.Format("{0}&chan_parent={1}", requrl, parent); 862 // requrl = String.Format("{0}&chan_parent={1}", requrl, parent);
859 // } 863 // }
860 864
861 if (description != null && description != String.Empty) 865 if (!string.IsNullOrEmpty(description))
862 { 866 {
863 requrl = String.Format("{0}&chan_desc={1}", requrl, description); 867 requrl = String.Format("{0}&chan_desc={1}", requrl, description);
864 } 868 }
@@ -1043,7 +1047,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1043 private XmlElement VivoxDeleteChannel(string parent, string channelid) 1047 private XmlElement VivoxDeleteChannel(string parent, string channelid)
1044 { 1048 {
1045 string requrl = String.Format(m_vivoxChannelDel, m_vivoxServer, "delete", channelid, m_authToken); 1049 string requrl = String.Format(m_vivoxChannelDel, m_vivoxServer, "delete", channelid, m_authToken);
1046 if (parent != null && parent != String.Empty) 1050 if (!string.IsNullOrEmpty(parent))
1047 { 1051 {
1048 requrl = String.Format("{0}&chan_parent={1}", requrl, parent); 1052 requrl = String.Format("{0}&chan_parent={1}", requrl, parent);
1049 } 1053 }
@@ -1111,27 +1115,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1111 1115
1112 doc = new XmlDocument(); 1116 doc = new XmlDocument();
1113 1117
1114 try 1118 // Let's serialize all calls to Vivox. Most of these are driven by
1119 // the clients (CAPs), when the user arrives at the region. We don't
1120 // want to issue many simultaneous http requests to Vivox, because mono
1121 // doesn't like that
1122 lock (m_Lock)
1115 { 1123 {
1116 // Otherwise prepare the request 1124 try
1117 m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl); 1125 {
1118 1126 // Otherwise prepare the request
1119 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl); 1127 m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl);
1120 HttpWebResponse rsp = null;
1121 1128
1122 // We are sending just parameters, no content 1129 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl);
1123 req.ContentLength = 0;
1124 1130
1125 // Send request and retrieve the response 1131 // We are sending just parameters, no content
1126 rsp = (HttpWebResponse)req.GetResponse(); 1132 req.ContentLength = 0;
1127 1133
1128 XmlTextReader rdr = new XmlTextReader(rsp.GetResponseStream()); 1134 // Send request and retrieve the response
1129 doc.Load(rdr); 1135 using (HttpWebResponse rsp = (HttpWebResponse)req.GetResponse())
1130 rdr.Close(); 1136 using (Stream s = rsp.GetResponseStream())
1131 } 1137 using (XmlTextReader rdr = new XmlTextReader(s))
1132 catch (Exception e) 1138 doc.Load(rdr);
1133 { 1139 }
1134 m_log.ErrorFormat("[VivoxVoice] Error in admin call : {0}", e.Message); 1140 catch (Exception e)
1141 {
1142 m_log.ErrorFormat("[VivoxVoice] Error in admin call : {0}", e.Message);
1143 }
1135 } 1144 }
1136 1145
1137 // If we're debugging server responses, dump the whole 1146 // If we're debugging server responses, dump the whole
@@ -1316,4 +1325,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1316 return false; 1325 return false;
1317 } 1326 }
1318 } 1327 }
1319} \ No newline at end of file 1328}
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
index 2802e2f..e1b6abb 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
@@ -55,8 +55,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
55 private IGroupsServicesConnector m_groupData = null; 55 private IGroupsServicesConnector m_groupData = null;
56 56
57 // Config Options 57 // Config Options
58 private bool m_groupMessagingEnabled = false; 58 private bool m_groupMessagingEnabled;
59 private bool m_debugEnabled = true; 59 private bool m_debugEnabled;
60 60
61 /// <summary> 61 /// <summary>
62 /// If enabled, module only tries to send group IMs to online users by querying cached presence information. 62 /// If enabled, module only tries to send group IMs to online users by querying cached presence information.
@@ -113,7 +113,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
113 if (m_messageOnlineAgentsOnly) 113 if (m_messageOnlineAgentsOnly)
114 m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>(); 114 m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>();
115 115
116 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); 116 m_debugEnabled = groupsConfig.GetBoolean("MessagingDebugEnabled", m_debugEnabled);
117 } 117 }
118 118
119 m_log.InfoFormat( 119 m_log.InfoFormat(
@@ -127,6 +127,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
127 return; 127 return;
128 128
129 scene.RegisterModuleInterface<IGroupsMessagingModule>(this); 129 scene.RegisterModuleInterface<IGroupsMessagingModule>(this);
130
131 scene.AddCommand(
132 "Debug",
133 this,
134 "debug groups messaging verbose",
135 "debug groups messaging verbose <true|false>",
136 "This setting turns on very verbose groups messaging debugging",
137 HandleDebugGroupsMessagingVerbose);
130 } 138 }
131 139
132 public void RegionLoaded(Scene scene) 140 public void RegionLoaded(Scene scene)
@@ -218,6 +226,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
218 226
219 #endregion 227 #endregion
220 228
229 private void HandleDebugGroupsMessagingVerbose(object modules, string[] args)
230 {
231 if (args.Length < 5)
232 {
233 MainConsole.Instance.Output("Usage: debug groups messaging verbose <true|false>");
234 return;
235 }
236
237 bool verbose = false;
238 if (!bool.TryParse(args[4], out verbose))
239 {
240 MainConsole.Instance.Output("Usage: debug groups messaging verbose <true|false>");
241 return;
242 }
243
244 m_debugEnabled = verbose;
245
246 MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled);
247 }
248
221 /// <summary> 249 /// <summary>
222 /// Not really needed, but does confirm that the group exists. 250 /// Not really needed, but does confirm that the group exists.
223 /// </summary> 251 /// </summary>
@@ -237,11 +265,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
237 return false; 265 return false;
238 } 266 }
239 } 267 }
240 268
241 public void SendMessageToGroup(GridInstantMessage im, UUID groupID) 269 public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
242 { 270 {
243 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); 271 SendMessageToGroup(im, groupID, new UUID(im.fromAgentID), null);
272 }
273
274 public void SendMessageToGroup(
275 GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func<GroupMembersData, bool> sendCondition)
276 {
277 int requestStartTick = Environment.TickCount;
278
279 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(sendingAgentForGroupCalls, groupID);
244 int groupMembersCount = groupMembers.Count; 280 int groupMembersCount = groupMembers.Count;
281 HashSet<string> attemptDeliveryUuidSet = null;
245 282
246 if (m_messageOnlineAgentsOnly) 283 if (m_messageOnlineAgentsOnly)
247 { 284 {
@@ -257,10 +294,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
257 m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); 294 m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
258 } 295 }
259 296
260 HashSet<string> onlineAgentsUuidSet = new HashSet<string>(); 297 attemptDeliveryUuidSet
261 Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); 298 = new HashSet<string>(Array.ConvertAll<PresenceInfo, string>(onlineAgents, pi => pi.UserID));
299
300 //Array.ForEach<PresenceInfo>(onlineAgents, pi => attemptDeliveryUuidSet.Add(pi.UserID));
262 301
263 groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); 302 //groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList();
264 303
265 // if (m_debugEnabled) 304 // if (m_debugEnabled)
266// m_log.DebugFormat( 305// m_log.DebugFormat(
@@ -269,26 +308,42 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
269 } 308 }
270 else 309 else
271 { 310 {
311 attemptDeliveryUuidSet
312 = new HashSet<string>(groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()));
313
272 if (m_debugEnabled) 314 if (m_debugEnabled)
273 m_log.DebugFormat( 315 m_log.DebugFormat(
274 "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", 316 "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members",
275 groupID, groupMembers.Count); 317 groupID, groupMembers.Count);
276 } 318 }
277
278 int requestStartTick = Environment.TickCount;
279 319
280 foreach (GroupMembersData member in groupMembers) 320 foreach (GroupMembersData member in groupMembers)
281 { 321 {
282 if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) 322 if (sendCondition != null)
323 {
324 if (!sendCondition(member))
325 {
326 if (m_debugEnabled)
327 m_log.DebugFormat(
328 "[GROUPS-MESSAGING]: Not sending to {0} as they do not fulfill send condition",
329 member.AgentID);
330
331 continue;
332 }
333 }
334 else if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID))
283 { 335 {
284 // Don't deliver messages to people who have dropped this session 336 // Don't deliver messages to people who have dropped this session
285 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); 337 if (m_debugEnabled)
338 m_log.DebugFormat(
339 "[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID);
340
286 continue; 341 continue;
287 } 342 }
288 343
289 // Copy Message 344 // Copy Message
290 GridInstantMessage msg = new GridInstantMessage(); 345 GridInstantMessage msg = new GridInstantMessage();
291 msg.imSessionID = groupID.Guid; 346 msg.imSessionID = im.imSessionID;
292 msg.fromAgentName = im.fromAgentName; 347 msg.fromAgentName = im.fromAgentName;
293 msg.message = im.message; 348 msg.message = im.message;
294 msg.dialog = im.dialog; 349 msg.dialog = im.dialog;
@@ -304,26 +359,51 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
304 359
305 msg.toAgentID = member.AgentID.Guid; 360 msg.toAgentID = member.AgentID.Guid;
306 361
307 IClientAPI client = GetActiveClient(member.AgentID); 362 if (attemptDeliveryUuidSet.Contains(member.AgentID.ToString()))
308 if (client == null)
309 { 363 {
310 // If they're not local, forward across the grid 364 IClientAPI client = GetActiveClient(member.AgentID);
311 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID); 365 if (client == null)
312 m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); 366 {
367 int startTick = Environment.TickCount;
368
369 // If they're not local, forward across the grid
370 m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
371
372 if (m_debugEnabled)
373 m_log.DebugFormat(
374 "[GROUPS-MESSAGING]: Delivering to {0} via grid took {1} ms",
375 member.AgentID, Environment.TickCount - startTick);
376 }
377 else
378 {
379 int startTick = Environment.TickCount;
380
381 ProcessMessageFromGroupSession(msg, client);
382
383 // Deliver locally, directly
384 if (m_debugEnabled)
385 m_log.DebugFormat(
386 "[GROUPS-MESSAGING]: Delivering to {0} locally took {1} ms",
387 member.AgentID, Environment.TickCount - startTick);
388 }
313 } 389 }
314 else 390 else
315 { 391 {
316 // Deliver locally, directly 392 int startTick = Environment.TickCount;
317 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); 393
318 ProcessMessageFromGroupSession(msg); 394 m_msgTransferModule.HandleUndeliverableMessage(msg, delegate(bool success) { });
395
396 if (m_debugEnabled)
397 m_log.DebugFormat(
398 "[GROUPS-MESSAGING]: Handling undeliverable message for {0} took {1} ms",
399 member.AgentID, Environment.TickCount - startTick);
319 } 400 }
320 } 401 }
321 402
322 // Temporary for assessing how long it still takes to send messages to large online groups. 403 if (m_debugEnabled)
323 if (m_messageOnlineAgentsOnly)
324 m_log.DebugFormat( 404 m_log.DebugFormat(
325 "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", 405 "[GROUPS-MESSAGING]: Total SendMessageToGroup for group {0} with {1} members, {2} candidates for delivery took {3} ms",
326 groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); 406 groupID, groupMembersCount, attemptDeliveryUuidSet.Count(), Environment.TickCount - requestStartTick);
327 } 407 }
328 408
329 #region SimGridEventHandlers 409 #region SimGridEventHandlers
@@ -348,7 +428,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
348 // Any other message type will not be delivered to a client by the 428 // Any other message type will not be delivered to a client by the
349 // Instant Message Module 429 // Instant Message Module
350 430
351
352 if (m_debugEnabled) 431 if (m_debugEnabled)
353 { 432 {
354 m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 433 m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
@@ -362,13 +441,35 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
362 || (msg.dialog == (byte)InstantMessageDialog.SessionAdd) 441 || (msg.dialog == (byte)InstantMessageDialog.SessionAdd)
363 || (msg.dialog == (byte)InstantMessageDialog.SessionDrop))) 442 || (msg.dialog == (byte)InstantMessageDialog.SessionDrop)))
364 { 443 {
365 ProcessMessageFromGroupSession(msg); 444 IClientAPI client = null;
445
446 if (msg.dialog == (byte)InstantMessageDialog.SessionSend)
447 {
448 client = GetActiveClient(new UUID(msg.toAgentID));
449
450 if (client != null)
451 {
452 if (m_debugEnabled)
453 m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} locally", client.Name);
454 }
455 else
456 {
457 m_log.WarnFormat("[GROUPS-MESSAGING]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
458
459 return;
460 }
461 }
462
463 ProcessMessageFromGroupSession(msg, client);
366 } 464 }
367 } 465 }
368 466
369 private void ProcessMessageFromGroupSession(GridInstantMessage msg) 467 private void ProcessMessageFromGroupSession(GridInstantMessage msg, IClientAPI client)
370 { 468 {
371 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); 469 if (m_debugEnabled)
470 m_log.DebugFormat(
471 "[GROUPS-MESSAGING]: Session message from {0} going to agent {1}, sessionID {2}, type {3}",
472 msg.fromAgentName, msg.toAgentID, msg.imSessionID, (InstantMessageDialog)msg.dialog);
372 473
373 UUID AgentID = new UUID(msg.fromAgentID); 474 UUID AgentID = new UUID(msg.fromAgentID);
374 UUID GroupID = new UUID(msg.imSessionID); 475 UUID GroupID = new UUID(msg.imSessionID);
@@ -392,74 +493,62 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
392 // Add them to the session for now, and Invite them 493 // Add them to the session for now, and Invite them
393 m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); 494 m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID);
394 495
395 UUID toAgentID = new UUID(msg.toAgentID); 496 GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null);
396 IClientAPI activeClient = GetActiveClient(toAgentID); 497 if (groupInfo != null)
397 if (activeClient != null)
398 { 498 {
399 GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); 499 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message");
400 if (groupInfo != null) 500
401 { 501 // Force? open the group session dialog???
402 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message"); 502 // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg);
403 503 IEventQueue eq = client.Scene.RequestModuleInterface<IEventQueue>();
404 // Force? open the group session dialog??? 504 eq.ChatterboxInvitation(
405 // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); 505 GroupID
406 IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>(); 506 , groupInfo.GroupName
407 eq.ChatterboxInvitation( 507 , new UUID(msg.fromAgentID)
408 GroupID 508 , msg.message
409 , groupInfo.GroupName 509 , new UUID(msg.toAgentID)
410 , new UUID(msg.fromAgentID) 510 , msg.fromAgentName
411 , msg.message 511 , msg.dialog
412 , new UUID(msg.toAgentID) 512 , msg.timestamp
413 , msg.fromAgentName 513 , msg.offline == 1
414 , msg.dialog 514 , (int)msg.ParentEstateID
415 , msg.timestamp 515 , msg.Position
416 , msg.offline == 1 516 , 1
417 , (int)msg.ParentEstateID 517 , new UUID(msg.imSessionID)
418 , msg.Position 518 , msg.fromGroup
419 , 1 519 , Utils.StringToBytes(groupInfo.GroupName)
420 , new UUID(msg.imSessionID) 520 );
421 , msg.fromGroup 521
422 , Utils.StringToBytes(groupInfo.GroupName) 522 eq.ChatterBoxSessionAgentListUpdates(
423 ); 523 new UUID(GroupID)
424 524 , new UUID(msg.fromAgentID)
425 eq.ChatterBoxSessionAgentListUpdates( 525 , new UUID(msg.toAgentID)
426 new UUID(GroupID) 526 , false //canVoiceChat
427 , new UUID(msg.fromAgentID) 527 , false //isModerator
428 , new UUID(msg.toAgentID) 528 , false //text mute
429 , false //canVoiceChat 529 );
430 , false //isModerator
431 , false //text mute
432 );
433 }
434 } 530 }
531
532 break;
435 } 533 }
436 else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID)) 534 else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID))
437 { 535 {
438 // User hasn't dropped, so they're in the session, 536 // User hasn't dropped, so they're in the session,
439 // maybe we should deliver it. 537 // maybe we should deliver it.
440 IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); 538 client.SendInstantMessage(msg);
441 if (client != null)
442 {
443 // Deliver locally, directly
444 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} locally", client.Name);
445 client.SendInstantMessage(msg);
446 }
447 else
448 {
449 m_log.WarnFormat("[GROUPS-MESSAGING]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
450 }
451 } 539 }
540
452 break; 541 break;
453 542
454 default: 543 default:
455 m_log.WarnFormat("[GROUPS-MESSAGING]: I don't know how to proccess a {0} message.", ((InstantMessageDialog)msg.dialog).ToString()); 544 client.SendInstantMessage(msg);
456 break; 545
546 break;;
457 } 547 }
458 } 548 }
459 549
460 #endregion 550 #endregion
461 551
462
463 #region ClientEvents 552 #region ClientEvents
464 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) 553 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
465 { 554 {
@@ -548,15 +637,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
548 // Don't log any normal IMs (privacy!) 637 // Don't log any normal IMs (privacy!)
549 if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent) 638 if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent)
550 { 639 {
551 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromGroup({0})", im.fromGroup ? "True" : "False"); 640 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: fromGroup({0})", im.fromGroup ? "True" : "False");
552 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: Dialog({0})", ((InstantMessageDialog)im.dialog).ToString()); 641 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: Dialog({0})", (InstantMessageDialog)im.dialog);
553 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromAgentID({0})", im.fromAgentID.ToString()); 642 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: fromAgentID({0})", im.fromAgentID);
554 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromAgentName({0})", im.fromAgentName.ToString()); 643 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: fromAgentName({0})", im.fromAgentName);
555 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: imSessionID({0})", im.imSessionID.ToString()); 644 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: imSessionID({0})", im.imSessionID);
556 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: message({0})", im.message.ToString()); 645 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: message({0})", im.message);
557 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: offline({0})", im.offline.ToString()); 646 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: offline({0})", im.offline);
558 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: toAgentID({0})", im.toAgentID.ToString()); 647 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: toAgentID({0})", im.toAgentID);
559 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket")); 648 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket"));
560 } 649 }
561 } 650 }
562 651
@@ -567,7 +656,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
567 /// </summary> 656 /// </summary>
568 private IClientAPI GetActiveClient(UUID agentID) 657 private IClientAPI GetActiveClient(UUID agentID)
569 { 658 {
570 if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID); 659 if (m_debugEnabled)
660 m_log.DebugFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID);
571 661
572 IClientAPI child = null; 662 IClientAPI child = null;
573 663
@@ -579,12 +669,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
579 { 669 {
580 if (!sp.IsChildAgent) 670 if (!sp.IsChildAgent)
581 { 671 {
582 if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", sp.ControllingClient.Name); 672 if (m_debugEnabled)
673 m_log.DebugFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", sp.ControllingClient.Name);
674
583 return sp.ControllingClient; 675 return sp.ControllingClient;
584 } 676 }
585 else 677 else
586 { 678 {
587 if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", sp.ControllingClient.Name); 679 if (m_debugEnabled)
680 m_log.DebugFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", sp.ControllingClient.Name);
681
588 child = sp.ControllingClient; 682 child = sp.ControllingClient;
589 } 683 }
590 } 684 }
@@ -593,12 +687,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
593 // If we didn't find a root, then just return whichever child we found, or null if none 687 // If we didn't find a root, then just return whichever child we found, or null if none
594 if (child == null) 688 if (child == null)
595 { 689 {
596 if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID); 690 if (m_debugEnabled)
691 m_log.DebugFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID);
597 } 692 }
598 else 693 else
599 { 694 {
600 if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name); 695 if (m_debugEnabled)
696 m_log.DebugFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name);
601 } 697 }
698
602 return child; 699 return child;
603 } 700 }
604 701
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index 29f9591..1565da9 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -35,10 +35,10 @@ using Nini.Config;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenMetaverse.StructuredData; 36using OpenMetaverse.StructuredData;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Communications;
39using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41using System.Text;
42using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; 42using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
43 43
44namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 44namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
@@ -76,9 +76,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
76 76
77 private List<Scene> m_sceneList = new List<Scene>(); 77 private List<Scene> m_sceneList = new List<Scene>();
78 78
79 private IMessageTransferModule m_msgTransferModule = null; 79 private IMessageTransferModule m_msgTransferModule;
80
81 private IGroupsMessagingModule m_groupsMessagingModule;
80 82
81 private IGroupsServicesConnector m_groupData = null; 83 private IGroupsServicesConnector m_groupData;
82 84
83 // Configuration settings 85 // Configuration settings
84 private bool m_groupsEnabled = false; 86 private bool m_groupsEnabled = false;
@@ -184,10 +186,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
184 if (m_msgTransferModule == null) 186 if (m_msgTransferModule == null)
185 { 187 {
186 m_groupsEnabled = false; 188 m_groupsEnabled = false;
187 m_log.Warn("[GROUPS]: Could not get MessageTransferModule"); 189 m_log.Warn("[GROUPS]: Could not get IMessageTransferModule");
188 } 190 }
189 } 191 }
190 192
193 if (m_groupsMessagingModule == null)
194 {
195 m_groupsMessagingModule = scene.RequestModuleInterface<IGroupsMessagingModule>();
196
197 // No message transfer module, no notices, group invites, rejects, ejects, etc
198 if (m_groupsMessagingModule == null)
199 m_log.Warn("[GROUPS]: Could not get IGroupsMessagingModule");
200 }
201
191 lock (m_sceneList) 202 lock (m_sceneList)
192 { 203 {
193 m_sceneList.Add(scene); 204 m_sceneList.Add(scene);
@@ -250,7 +261,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
250 261
251 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; 262 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
252 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; 263 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
253 client.OnDirFindQuery += OnDirFindQuery;
254 client.OnRequestAvatarProperties += OnRequestAvatarProperties; 264 client.OnRequestAvatarProperties += OnRequestAvatarProperties;
255 265
256 // Used for Notices and Group Invites/Accept/Reject 266 // Used for Notices and Group Invites/Accept/Reject
@@ -303,21 +313,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
303 } 313 }
304 */ 314 */
305 315
306 void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart)
307 {
308 if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups)
309 {
310 if (m_debugEnabled)
311 m_log.DebugFormat(
312 "[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})",
313 System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart);
314
315 // TODO: This currently ignores pretty much all the query flags including Mature and sort order
316 remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentID(remoteClient), queryText).ToArray());
317 }
318
319 }
320
321 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) 316 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID)
322 { 317 {
323 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 318 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
@@ -361,7 +356,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
361 356
362 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) 357 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
363 { 358 {
364 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 359 if (m_debugEnabled)
360 m_log.DebugFormat(
361 "[GROUPS]: {0} called for {1}, message type {2}",
362 System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name, (InstantMessageDialog)im.dialog);
365 363
366 // Group invitations 364 // Group invitations
367 if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) 365 if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline))
@@ -437,81 +435,160 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
437 string Subject = im.message.Substring(0, im.message.IndexOf('|')); 435 string Subject = im.message.Substring(0, im.message.IndexOf('|'));
438 string Message = im.message.Substring(Subject.Length + 1); 436 string Message = im.message.Substring(Subject.Length + 1);
439 437
438 InventoryItemBase item = null;
439 bool hasAttachment = false;
440 UUID itemID = UUID.Zero; //Assignment to quiet compiler
441 UUID ownerID = UUID.Zero; //Assignment to quiet compiler
440 byte[] bucket; 442 byte[] bucket;
441 443
442 if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0)) 444 if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0)
443 {
444 bucket = new byte[19];
445 bucket[0] = 0; //dunno
446 bucket[1] = 0; //dunno
447 GroupID.ToBytes(bucket, 2);
448 bucket[18] = 0; //dunno
449 }
450 else
451 { 445 {
452 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket); 446 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
453 binBucket = binBucket.Remove(0, 14).Trim(); 447 binBucket = binBucket.Remove(0, 14).Trim();
454 if (m_debugEnabled) 448
449 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket);
450 if (binBucketOSD is OSD)
455 { 451 {
456 m_log.WarnFormat("I don't understand a group notice binary bucket of: {0}", binBucket); 452 OSDMap binBucketMap = (OSDMap)binBucketOSD;
453
454 itemID = binBucketMap["item_id"].AsUUID();
455 ownerID = binBucketMap["owner_id"].AsUUID();
456
457 //Attempt to get the details of the attached item.
458 //If sender doesn't own the attachment, the item
459 //variable will be set to null and attachment will
460 //not be included with the group notice.
461 Scene scene = (Scene)remoteClient.Scene;
462 item = new InventoryItemBase(itemID, ownerID);
463 item = scene.InventoryService.GetItem(item);
457 464
458 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket); 465 if (item != null)
459
460 foreach (string key in binBucketOSD.Keys)
461 { 466 {
462 if (binBucketOSD.ContainsKey(key)) 467 //Got item details so include the attachment.
463 { 468 hasAttachment = true;
464 m_log.WarnFormat("{0}: {1}", key, binBucketOSD[key].ToString());
465 }
466 } 469 }
467 } 470 }
468 471 else
469 // treat as if no attachment 472 {
473 m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType());
474 }
475 }
476
477 if (hasAttachment)
478 {
479 //Bucket contains information about attachment.
480 //
481 //Byte offset and description of bucket data:
482 //0: 1 byte indicating if attachment is present
483 //1: 1 byte indicating the type of attachment
484 //2: 16 bytes - Group UUID
485 //18: 16 bytes - UUID of the attachment owner
486 //34: 16 bytes - UUID of the attachment
487 //50: variable - Name of the attachment
488 //??: NUL byte to terminate the attachment name
489 byte[] name = Encoding.UTF8.GetBytes(item.Name);
490 bucket = new byte[51 + name.Length];//3 bytes, 3 UUIDs, and name
491 bucket[0] = 1; //Has attachment flag
492 bucket[1] = (byte)item.InvType; //Type of Attachment
493 GroupID.ToBytes(bucket, 2);
494 ownerID.ToBytes(bucket, 18);
495 itemID.ToBytes(bucket, 34);
496 name.CopyTo(bucket, 50);
497 }
498 else
499 {
470 bucket = new byte[19]; 500 bucket = new byte[19];
471 bucket[0] = 0; //dunno 501 bucket[0] = 0; //Has attachment flag
472 bucket[1] = 0; //dunno 502 bucket[1] = 0; //Type of attachment
473 GroupID.ToBytes(bucket, 2); 503 GroupID.ToBytes(bucket, 2);
474 bucket[18] = 0; //dunno 504 bucket[18] = 0; //NUL terminate name of attachment
475 } 505 }
476 506
477
478 m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); 507 m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket);
479 if (OnNewGroupNotice != null) 508 if (OnNewGroupNotice != null)
480 { 509 {
481 OnNewGroupNotice(GroupID, NoticeID); 510 OnNewGroupNotice(GroupID, NoticeID);
482 } 511 }
483 512
484 // Send notice out to everyone that wants notices 513 if (m_debugEnabled)
485 foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID))
486 { 514 {
487 if (m_debugEnabled) 515 foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID))
488 { 516 {
489 UserAccount targetUser = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, member.AgentID); 517 if (m_debugEnabled)
490 if (targetUser != null)
491 { 518 {
492 m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices); 519 UserAccount targetUser
493 } 520 = m_sceneList[0].UserAccountService.GetUserAccount(
494 else 521 remoteClient.Scene.RegionInfo.ScopeID, member.AgentID);
495 { 522
496 m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, member.AgentID, member.AcceptNotices); 523 if (targetUser != null)
524 {
525 m_log.DebugFormat(
526 "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})",
527 NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices);
528 }
529 else
530 {
531 m_log.DebugFormat(
532 "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})",
533 NoticeID, member.AgentID, member.AcceptNotices);
534 }
497 } 535 }
498 } 536 }
537 }
499 538
500 if (member.AcceptNotices) 539 GridInstantMessage msg
501 { 540 = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
502 // Build notice IIM
503 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
504 541
505 msg.toAgentID = member.AgentID.Guid; 542 if (m_groupsMessagingModule != null)
506 OutgoingInstantMessage(msg, member.AgentID); 543 m_groupsMessagingModule.SendMessageToGroup(
507 } 544 msg, GroupID, remoteClient.AgentId, gmd => gmd.AcceptNotices);
545 }
546 }
547
548 if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted)
549 {
550 //Is bucket large enough to hold UUID of the attachment?
551 if (im.binaryBucket.Length < 16)
552 return;
553
554 UUID noticeID = new UUID(im.imSessionID);
555
556 if (m_debugEnabled)
557 m_log.DebugFormat("[GROUPS]: Requesting notice {0} for {1}", noticeID, remoteClient.AgentId);
558
559 GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID);
560 if (notice != null)
561 {
562 UUID giver = new UUID(notice.BinaryBucket, 18);
563 UUID attachmentUUID = new UUID(notice.BinaryBucket, 34);
564
565 if (m_debugEnabled)
566 m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId);
567
568 string message;
569 InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId,
570 giver, attachmentUUID, out message);
571
572 if (itemCopy == null)
573 {
574 remoteClient.SendAgentAlertMessage(message, false);
575 return;
508 } 576 }
577
578 remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
579 }
580 else
581 {
582 if (m_debugEnabled)
583 m_log.DebugFormat(
584 "[GROUPS]: Could not find notice {0} for {1} on GroupNoticeInventoryAccepted.",
585 noticeID, remoteClient.AgentId);
509 } 586 }
510 } 587 }
511 588
512 // Interop, received special 210 code for ejecting a group member 589 // Interop, received special 210 code for ejecting a group member
513 // this only works within the comms servers domain, and won't work hypergrid 590 // this only works within the comms servers domain, and won't work hypergrid
514 // TODO:FIXME: Use a presense server of some kind to find out where the 591 // TODO:FIXME: Use a presence server of some kind to find out where the
515 // client actually is, and try contacting that region directly to notify them, 592 // client actually is, and try contacting that region directly to notify them,
516 // or provide the notification via xmlrpc update queue 593 // or provide the notification via xmlrpc update queue
517 if ((im.dialog == 210)) 594 if ((im.dialog == 210))
@@ -764,7 +841,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
764 remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient funds to create a group."); 841 remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient funds to create a group.");
765 return UUID.Zero; 842 return UUID.Zero;
766 } 843 }
767 money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, "Group Creation"); 844 money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, MoneyTransactionType.GroupCreate);
768 } 845 }
769 UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); 846 UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient));
770 847
@@ -889,26 +966,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
889 966
890 if (data != null) 967 if (data != null)
891 { 968 {
892 GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); 969 GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested);
893
894 GridInstantMessage msg = new GridInstantMessage();
895 msg.imSessionID = UUID.Zero.Guid;
896 msg.fromAgentID = data.GroupID.Guid;
897 msg.toAgentID = GetRequestingAgentID(remoteClient).Guid;
898 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
899 msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName;
900 msg.message = data.noticeData.Subject + "|" + data.Message;
901 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested;
902 msg.fromGroup = true;
903 msg.offline = (byte)0;
904 msg.ParentEstateID = 0;
905 msg.Position = Vector3.Zero;
906 msg.RegionID = UUID.Zero.Guid;
907 msg.binaryBucket = data.BinaryBucket;
908 970
909 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); 971 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient));
910 } 972 }
911
912 } 973 }
913 974
914 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog) 975 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog)
@@ -916,10 +977,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
916 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 977 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
917 978
918 GridInstantMessage msg = new GridInstantMessage(); 979 GridInstantMessage msg = new GridInstantMessage();
919 msg.imSessionID = UUID.Zero.Guid; 980 byte[] bucket;
981
982 msg.imSessionID = groupNoticeID.Guid;
920 msg.toAgentID = agentID.Guid; 983 msg.toAgentID = agentID.Guid;
921 msg.dialog = dialog; 984 msg.dialog = dialog;
922 // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice;
923 msg.fromGroup = true; 985 msg.fromGroup = true;
924 msg.offline = (byte)0; 986 msg.offline = (byte)0;
925 msg.ParentEstateID = 0; 987 msg.ParentEstateID = 0;
@@ -933,13 +995,38 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
933 msg.timestamp = info.noticeData.Timestamp; 995 msg.timestamp = info.noticeData.Timestamp;
934 msg.fromAgentName = info.noticeData.FromName; 996 msg.fromAgentName = info.noticeData.FromName;
935 msg.message = info.noticeData.Subject + "|" + info.Message; 997 msg.message = info.noticeData.Subject + "|" + info.Message;
936 msg.binaryBucket = info.BinaryBucket; 998
999 if (info.BinaryBucket[0] > 0)
1000 {
1001 //32 is due to not needing space for two of the UUIDs.
1002 //(Don't need UUID of attachment or its owner in IM)
1003 //50 offset gets us to start of attachment name.
1004 //We are skipping the attachment flag, type, and
1005 //the three UUID fields at the start of the bucket.
1006 bucket = new byte[info.BinaryBucket.Length-32];
1007 bucket[0] = 1; //Has attachment
1008 bucket[1] = info.BinaryBucket[1];
1009 Array.Copy(info.BinaryBucket, 50,
1010 bucket, 18, info.BinaryBucket.Length-50);
1011 }
1012 else
1013 {
1014 bucket = new byte[19];
1015 bucket[0] = 0; //No attachment
1016 bucket[1] = 0; //Attachment type
1017 bucket[18] = 0; //NUL terminate name
1018 }
1019
1020 info.GroupID.ToBytes(bucket, 2);
1021 msg.binaryBucket = bucket;
937 } 1022 }
938 else 1023 else
939 { 1024 {
940 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID); 1025 if (m_debugEnabled)
1026 m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID);
1027
941 msg.fromAgentID = UUID.Zero.Guid; 1028 msg.fromAgentID = UUID.Zero.Guid;
942 msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); ; 1029 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
943 msg.fromAgentName = string.Empty; 1030 msg.fromAgentName = string.Empty;
944 msg.message = string.Empty; 1031 msg.message = string.Empty;
945 msg.binaryBucket = new byte[0]; 1032 msg.binaryBucket = new byte[0];
@@ -1063,7 +1150,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1063 // Message to ejector 1150 // Message to ejector
1064 // Interop, received special 210 code for ejecting a group member 1151 // Interop, received special 210 code for ejecting a group member
1065 // this only works within the comms servers domain, and won't work hypergrid 1152 // this only works within the comms servers domain, and won't work hypergrid
1066 // TODO:FIXME: Use a presense server of some kind to find out where the 1153 // TODO:FIXME: Use a presence server of some kind to find out where the
1067 // client actually is, and try contacting that region directly to notify them, 1154 // client actually is, and try contacting that region directly to notify them,
1068 // or provide the notification via xmlrpc update queue 1155 // or provide the notification via xmlrpc update queue
1069 1156
@@ -1178,6 +1265,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1178 } 1265 }
1179 } 1266 }
1180 1267
1268 public List<DirGroupsReplyData> FindGroups(IClientAPI remoteClient, string query)
1269 {
1270 return m_groupData.FindGroups(GetRequestingAgentID(remoteClient), query);
1271 }
1272
1273
1181 #endregion 1274 #endregion
1182 1275
1183 #region Client/Update Tools 1276 #region Client/Update Tools
@@ -1222,7 +1315,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1222 AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); 1315 AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID));
1223 AgentData.Add(AgentDataMap); 1316 AgentData.Add(AgentDataMap);
1224 1317
1225
1226 OSDArray GroupData = new OSDArray(data.Length); 1318 OSDArray GroupData = new OSDArray(data.Length);
1227 OSDArray NewGroupData = new OSDArray(data.Length); 1319 OSDArray NewGroupData = new OSDArray(data.Length);
1228 1320
@@ -1288,7 +1380,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1288 presence.Grouptitle = Title; 1380 presence.Grouptitle = Title;
1289 1381
1290 if (! presence.IsChildAgent) 1382 if (! presence.IsChildAgent)
1291 presence.SendAvatarDataToAllAgents(); 1383 presence.SendAvatarDataToAllClients();
1292 } 1384 }
1293 } 1385 }
1294 } 1386 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
index 7bae8f7..1cb4747 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
@@ -42,7 +42,6 @@ using OpenMetaverse;
42using OpenMetaverse.StructuredData; 42using OpenMetaverse.StructuredData;
43 43
44using OpenSim.Framework; 44using OpenSim.Framework;
45using OpenSim.Framework.Communications;
46using OpenSim.Region.Framework.Interfaces; 45using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Services.Interfaces; 46using OpenSim.Services.Interfaces;
48 47
@@ -212,8 +211,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
212 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name); 211 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
213 212
214 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); 213 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
215 if ((m_groupsServerURI == null) || 214 if (string.IsNullOrEmpty(m_groupsServerURI))
216 (m_groupsServerURI == string.Empty))
217 { 215 {
218 m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]"); 216 m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]");
219 m_connectorEnabled = false; 217 m_connectorEnabled = false;
@@ -438,7 +436,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
438 return null; 436 return null;
439 } 437 }
440 } 438 }
441 else if ((groupName != null) && (groupName != string.Empty)) 439 else if (!string.IsNullOrEmpty(groupName))
442 { 440 {
443 if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap)) 441 if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap))
444 { 442 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
index c1bdacb..9a42bac 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
@@ -26,15 +26,25 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
29using System.Reflection; 32using System.Reflection;
30using Nini.Config; 33using Nini.Config;
31using NUnit.Framework; 34using NUnit.Framework;
32using OpenMetaverse; 35using OpenMetaverse;
36using OpenMetaverse.Messages.Linden;
37using OpenMetaverse.Packets;
38using OpenMetaverse.StructuredData;
33using OpenSim.Framework; 39using OpenSim.Framework;
34using OpenSim.Framework.Communications; 40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.ClientStack.Linden;
43using OpenSim.Region.CoreModules.Avatar.InstantMessage;
44using OpenSim.Region.CoreModules.Framework;
35using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups;
36using OpenSim.Tests.Common; 47using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock;
38 48
39namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests 49namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
40{ 50{
@@ -44,11 +54,28 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
44 [TestFixture] 54 [TestFixture]
45 public class GroupsModuleTests : OpenSimTestCase 55 public class GroupsModuleTests : OpenSimTestCase
46 { 56 {
57 [SetUp]
58 public override void SetUp()
59 {
60 base.SetUp();
61
62 uint port = 9999;
63 uint sslPort = 9998;
64
65 // This is an unfortunate bit of clean up we have to do because MainServer manages things through static
66 // variables and the VM is not restarted between tests.
67 MainServer.RemoveHttpServer(port);
68
69 BaseHttpServer server = new BaseHttpServer(port, false, sslPort, "");
70 MainServer.AddHttpServer(server);
71 MainServer.Instance = server;
72 }
73
47 [Test] 74 [Test]
48 public void TestBasic() 75 public void TestSendAgentGroupDataUpdate()
49 { 76 {
50 TestHelpers.InMethod(); 77 TestHelpers.InMethod();
51// log4net.Config.XmlConfigurator.Configure(); 78// TestHelpers.EnableLogging();
52 79
53 TestScene scene = new SceneHelpers().SetupScene(); 80 TestScene scene = new SceneHelpers().SetupScene();
54 IConfigSource configSource = new IniConfigSource(); 81 IConfigSource configSource = new IniConfigSource();
@@ -56,8 +83,185 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
56 config.Set("Enabled", true); 83 config.Set("Enabled", true);
57 config.Set("Module", "GroupsModule"); 84 config.Set("Module", "GroupsModule");
58 config.Set("DebugEnabled", true); 85 config.Set("DebugEnabled", true);
86
87 GroupsModule gm = new GroupsModule();
88 EventQueueGetModule eqgm = new EventQueueGetModule();
89
90 // We need a capabilities module active so that adding the scene presence creates an event queue in the
91 // EventQueueGetModule
59 SceneHelpers.SetupSceneModules( 92 SceneHelpers.SetupSceneModules(
60 scene, configSource, new object[] { new MockGroupsServicesConnector() }); 93 scene, configSource, gm, new MockGroupsServicesConnector(), new CapabilitiesModule(), eqgm);
94
95 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseStem("1"));
96
97 gm.SendAgentGroupDataUpdate(sp.ControllingClient);
98
99 Hashtable eventsResponse = eqgm.GetEvents(UUID.Zero, sp.UUID);
100
101 Assert.That((int)eventsResponse["int_response_code"], Is.EqualTo((int)HttpStatusCode.OK));
102
103// Console.WriteLine("Response [{0}]", (string)eventsResponse["str_response_string"]);
104
105 OSDMap rawOsd = (OSDMap)OSDParser.DeserializeLLSDXml((string)eventsResponse["str_response_string"]);
106 OSDArray eventsOsd = (OSDArray)rawOsd["events"];
107
108 bool foundUpdate = false;
109 foreach (OSD osd in eventsOsd)
110 {
111 OSDMap eventOsd = (OSDMap)osd;
112
113 if (eventOsd["message"] == "AgentGroupDataUpdate")
114 foundUpdate = true;
115 }
116
117 Assert.That(foundUpdate, Is.True, "Did not find AgentGroupDataUpdate in response");
118
119 // TODO: More checking of more actual event data.
120 }
121
122 [Test]
123 public void TestSendGroupNotice()
124 {
125 TestHelpers.InMethod();
126// TestHelpers.EnableLogging();
127
128 TestScene scene = new SceneHelpers().SetupScene();
129
130 MessageTransferModule mtm = new MessageTransferModule();
131 GroupsModule gm = new GroupsModule();
132 GroupsMessagingModule gmm = new GroupsMessagingModule();
133 MockGroupsServicesConnector mgsc = new MockGroupsServicesConnector();
134
135 IConfigSource configSource = new IniConfigSource();
136
137 {
138 IConfig config = configSource.AddConfig("Messaging");
139 config.Set("MessageTransferModule", mtm.Name);
140 }
141
142 {
143 IConfig config = configSource.AddConfig("Groups");
144 config.Set("Enabled", true);
145 config.Set("Module", gm.Name);
146 config.Set("DebugEnabled", true);
147 config.Set("MessagingModule", gmm.Name);
148 config.Set("MessagingEnabled", true);
149 }
150
151 SceneHelpers.SetupSceneModules(scene, configSource, mgsc, mtm, gm, gmm);
152
153 UUID userId = TestHelpers.ParseTail(0x1);
154 string subjectText = "newman";
155 string messageText = "Hello";
156 string combinedSubjectMessage = string.Format("{0}|{1}", subjectText, messageText);
157
158 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
159 TestClient tc = (TestClient)sp.ControllingClient;
160
161 UUID groupID = gm.CreateGroup(tc, "group1", null, true, UUID.Zero, 0, true, true, true);
162 gm.JoinGroupRequest(tc, groupID);
163
164 // Create a second user who doesn't want to receive notices
165 ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x2));
166 TestClient tc2 = (TestClient)sp2.ControllingClient;
167 gm.JoinGroupRequest(tc2, groupID);
168 gm.SetGroupAcceptNotices(tc2, groupID, false, true);
169
170 List<GridInstantMessage> spReceivedMessages = new List<GridInstantMessage>();
171 tc.OnReceivedInstantMessage += im => spReceivedMessages.Add(im);
172
173 List<GridInstantMessage> sp2ReceivedMessages = new List<GridInstantMessage>();
174 tc2.OnReceivedInstantMessage += im => sp2ReceivedMessages.Add(im);
175
176 GridInstantMessage noticeIm = new GridInstantMessage();
177 noticeIm.fromAgentID = userId.Guid;
178 noticeIm.toAgentID = groupID.Guid;
179 noticeIm.message = combinedSubjectMessage;
180 noticeIm.dialog = (byte)InstantMessageDialog.GroupNotice;
181
182 tc.HandleImprovedInstantMessage(noticeIm);
183
184 Assert.That(spReceivedMessages.Count, Is.EqualTo(1));
185 Assert.That(spReceivedMessages[0].message, Is.EqualTo(combinedSubjectMessage));
186
187 List<GroupNoticeData> notices = mgsc.GetGroupNotices(UUID.Zero, groupID);
188 Assert.AreEqual(1, notices.Count);
189
190 // OpenSimulator (possibly also SL) transport the notice ID as the session ID!
191 Assert.AreEqual(notices[0].NoticeID.Guid, spReceivedMessages[0].imSessionID);
192
193 Assert.That(sp2ReceivedMessages.Count, Is.EqualTo(0));
194 }
195
196 /// <summary>
197 /// Run test with the MessageOnlineUsersOnly flag set.
198 /// </summary>
199 [Test]
200 public void TestSendGroupNoticeOnlineOnly()
201 {
202 TestHelpers.InMethod();
203 // TestHelpers.EnableLogging();
204
205 TestScene scene = new SceneHelpers().SetupScene();
206
207 MessageTransferModule mtm = new MessageTransferModule();
208 GroupsModule gm = new GroupsModule();
209 GroupsMessagingModule gmm = new GroupsMessagingModule();
210
211 IConfigSource configSource = new IniConfigSource();
212
213 {
214 IConfig config = configSource.AddConfig("Messaging");
215 config.Set("MessageTransferModule", mtm.Name);
216 }
217
218 {
219 IConfig config = configSource.AddConfig("Groups");
220 config.Set("Enabled", true);
221 config.Set("Module", gm.Name);
222 config.Set("DebugEnabled", true);
223 config.Set("MessagingModule", gmm.Name);
224 config.Set("MessagingEnabled", true);
225 config.Set("MessageOnlineUsersOnly", true);
226 }
227
228 SceneHelpers.SetupSceneModules(scene, configSource, new MockGroupsServicesConnector(), mtm, gm, gmm);
229
230 UUID userId = TestHelpers.ParseTail(0x1);
231 string subjectText = "newman";
232 string messageText = "Hello";
233 string combinedSubjectMessage = string.Format("{0}|{1}", subjectText, messageText);
234
235 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
236 TestClient tc = (TestClient)sp.ControllingClient;
237
238 UUID groupID = gm.CreateGroup(tc, "group1", null, true, UUID.Zero, 0, true, true, true);
239 gm.JoinGroupRequest(tc, groupID);
240
241 // Create a second user who doesn't want to receive notices
242 ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x2));
243 TestClient tc2 = (TestClient)sp2.ControllingClient;
244 gm.JoinGroupRequest(tc2, groupID);
245 gm.SetGroupAcceptNotices(tc2, groupID, false, true);
246
247 List<GridInstantMessage> spReceivedMessages = new List<GridInstantMessage>();
248 tc.OnReceivedInstantMessage += im => spReceivedMessages.Add(im);
249
250 List<GridInstantMessage> sp2ReceivedMessages = new List<GridInstantMessage>();
251 tc2.OnReceivedInstantMessage += im => sp2ReceivedMessages.Add(im);
252
253 GridInstantMessage noticeIm = new GridInstantMessage();
254 noticeIm.fromAgentID = userId.Guid;
255 noticeIm.toAgentID = groupID.Guid;
256 noticeIm.message = combinedSubjectMessage;
257 noticeIm.dialog = (byte)InstantMessageDialog.GroupNotice;
258
259 tc.HandleImprovedInstantMessage(noticeIm);
260
261 Assert.That(spReceivedMessages.Count, Is.EqualTo(1));
262 Assert.That(spReceivedMessages[0].message, Is.EqualTo(combinedSubjectMessage));
263
264 Assert.That(sp2ReceivedMessages.Count, Is.EqualTo(0));
61 } 265 }
62 } 266 }
63} \ No newline at end of file 267} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
index 1101851..20555e4 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
@@ -41,7 +41,6 @@ using OpenMetaverse;
41using OpenMetaverse.StructuredData; 41using OpenMetaverse.StructuredData;
42 42
43using OpenSim.Framework; 43using OpenSim.Framework;
44using OpenSim.Framework.Communications;
45using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
47 46
@@ -168,8 +167,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
168 m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name); 167 m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
169 168
170 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); 169 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
171 if ((m_groupsServerURI == null) || 170 if (string.IsNullOrEmpty(m_groupsServerURI))
172 (m_groupsServerURI == string.Empty))
173 { 171 {
174 m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]"); 172 m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]");
175 m_connectorEnabled = false; 173 m_connectorEnabled = false;
@@ -354,7 +352,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
354 { 352 {
355 param["GroupID"] = GroupID.ToString(); 353 param["GroupID"] = GroupID.ToString();
356 } 354 }
357 if ((GroupName != null) && (GroupName != string.Empty)) 355 if (!string.IsNullOrEmpty(GroupName))
358 { 356 {
359 param["Name"] = GroupName.ToString(); 357 param["Name"] = GroupName.ToString();
360 } 358 }
@@ -1013,7 +1011,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1013 Hashtable respData = (Hashtable)resp.Value; 1011 Hashtable respData = (Hashtable)resp.Value;
1014 if (respData.Contains("error") && !respData.Contains("succeed")) 1012 if (respData.Contains("error") && !respData.Contains("succeed"))
1015 { 1013 {
1016 LogRespDataToConsoleError(respData); 1014 LogRespDataToConsoleError(requestingAgentID, function, param, respData);
1017 } 1015 }
1018 1016
1019 return respData; 1017 return respData;
@@ -1041,20 +1039,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1041 return error; 1039 return error;
1042 } 1040 }
1043 1041
1044 private void LogRespDataToConsoleError(Hashtable respData) 1042 private void LogRespDataToConsoleError(UUID requestingAgentID, string function, Hashtable param, Hashtable respData)
1045 { 1043 {
1046 m_log.Error("[XMLRPC-GROUPS-CONNECTOR]: Error:"); 1044 m_log.ErrorFormat(
1047 1045 "[XMLRPC-GROUPS-CONNECTOR]: Error when calling {0} for {1} with params {2}. Response params are {3}",
1048 foreach (string key in respData.Keys) 1046 function, requestingAgentID, Util.PrettyFormatToSingleLine(param), Util.PrettyFormatToSingleLine(respData));
1049 {
1050 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Key: {0}", key);
1051
1052 string[] lines = respData[key].ToString().Split(new char[] { '\n' });
1053 foreach (string line in lines)
1054 {
1055 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}", line);
1056 }
1057 }
1058 } 1047 }
1059 1048
1060 /// <summary> 1049 /// <summary>
@@ -1146,28 +1135,38 @@ namespace Nwc.XmlRpc
1146 request.AllowWriteStreamBuffering = true; 1135 request.AllowWriteStreamBuffering = true;
1147 request.KeepAlive = !_disableKeepAlive; 1136 request.KeepAlive = !_disableKeepAlive;
1148 1137
1149 Stream stream = request.GetRequestStream(); 1138 using (Stream stream = request.GetRequestStream())
1150 XmlTextWriter xml = new XmlTextWriter(stream, Encoding.ASCII);
1151 _serializer.Serialize(xml, this);
1152 xml.Flush();
1153 xml.Close();
1154
1155 HttpWebResponse response = (HttpWebResponse)request.GetResponse();
1156 StreamReader input = new StreamReader(response.GetResponseStream());
1157
1158 string inputXml = input.ReadToEnd();
1159 XmlRpcResponse resp;
1160 try
1161 { 1139 {
1162 resp = (XmlRpcResponse)_deserializer.Deserialize(inputXml); 1140 using (XmlTextWriter xml = new XmlTextWriter(stream, Encoding.ASCII))
1141 {
1142 _serializer.Serialize(xml, this);
1143 xml.Flush();
1144 }
1163 } 1145 }
1164 catch (Exception e) 1146
1147 XmlRpcResponse resp;
1148
1149 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
1165 { 1150 {
1166 RequestResponse = inputXml; 1151 using (Stream s = response.GetResponseStream())
1167 throw e; 1152 {
1153 using (StreamReader input = new StreamReader(s))
1154 {
1155 string inputXml = input.ReadToEnd();
1156
1157 try
1158 {
1159 resp = (XmlRpcResponse)_deserializer.Deserialize(inputXml);
1160 }
1161 catch (Exception e)
1162 {
1163 RequestResponse = inputXml;
1164 throw e;
1165 }
1166 }
1167 }
1168 } 1168 }
1169 input.Close(); 1169
1170 response.Close();
1171 return resp; 1170 return resp;
1172 } 1171 }
1173 } 1172 }
diff --git a/OpenSim/Region/DataSnapshot/DataRequestHandler.cs b/OpenSim/Region/OptionalModules/DataSnapshot/DataRequestHandler.cs
index 32e93b4..50276ae 100644
--- a/OpenSim/Region/DataSnapshot/DataRequestHandler.cs
+++ b/OpenSim/Region/OptionalModules/DataSnapshot/DataRequestHandler.cs
@@ -63,7 +63,7 @@ namespace OpenSim.Region.DataSnapshot
63 63
64 public Hashtable OnGetSnapshot(Hashtable keysvals) 64 public Hashtable OnGetSnapshot(Hashtable keysvals)
65 { 65 {
66 m_log.Info("[DATASNAPSHOT] Received collection request"); 66 m_log.Debug("[DATASNAPSHOT] Received collection request");
67 Hashtable reply = new Hashtable(); 67 Hashtable reply = new Hashtable();
68 int statuscode = 200; 68 int statuscode = 200;
69 69
@@ -80,7 +80,7 @@ namespace OpenSim.Region.DataSnapshot
80 80
81 public Hashtable OnValidate(Hashtable keysvals) 81 public Hashtable OnValidate(Hashtable keysvals)
82 { 82 {
83 m_log.Info("[DATASNAPSHOT] Received validation request"); 83 m_log.Debug("[DATASNAPSHOT] Received validation request");
84 Hashtable reply = new Hashtable(); 84 Hashtable reply = new Hashtable();
85 int statuscode = 200; 85 int statuscode = 200;
86 86
diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs
index 5e62f23..0c3446d 100644
--- a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
+++ b/OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs
@@ -29,22 +29,20 @@
29using System; 29using System;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Linq;
32using System.Net; 33using System.Net;
33using System.Reflection; 34using System.Reflection;
35using System.Text;
34using System.Xml; 36using System.Xml;
35using log4net; 37using log4net;
36using Nini.Config; 38using Nini.Config;
37using OpenMetaverse; 39using OpenMetaverse;
38using Mono.Addins; 40using Mono.Addins;
39using OpenSim.Framework; 41using OpenSim.Framework;
40using OpenSim.Framework.Communications;
41using OpenSim.Region.DataSnapshot.Interfaces; 42using OpenSim.Region.DataSnapshot.Interfaces;
42using OpenSim.Region.Framework.Interfaces; 43using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
44 45
45[assembly: Addin("DataSnapshot", "0.1")]
46[assembly: AddinDependency("OpenSim", "0.5")]
47
48namespace OpenSim.Region.DataSnapshot 46namespace OpenSim.Region.DataSnapshot
49{ 47{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DataSnapshotManager")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DataSnapshotManager")]
@@ -113,9 +111,17 @@ namespace OpenSim.Region.DataSnapshot
113 try 111 try
114 { 112 {
115 m_enabled = config.Configs["DataSnapshot"].GetBoolean("index_sims", m_enabled); 113 m_enabled = config.Configs["DataSnapshot"].GetBoolean("index_sims", m_enabled);
116 IConfig conf = config.Configs["GridService"]; 114 string gatekeeper = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI",
117 if (conf != null) 115 new string[] { "Startup", "Hypergrid", "GridService" }, String.Empty);
118 m_gridinfo.Add("gatekeeperURL", conf.GetString("Gatekeeper", String.Empty)); 116 // Legacy. Remove soon!
117 if (string.IsNullOrEmpty(gatekeeper))
118 {
119 IConfig conf = config.Configs["GridService"];
120 if (conf != null)
121 gatekeeper = conf.GetString("Gatekeeper", gatekeeper);
122 }
123 if (!string.IsNullOrEmpty(gatekeeper))
124 m_gridinfo.Add("gatekeeperURL", gatekeeper);
119 125
120 m_gridinfo.Add( 126 m_gridinfo.Add(
121 "name", config.Configs["DataSnapshot"].GetString("gridname", "the lost continent of hippo")); 127 "name", config.Configs["DataSnapshot"].GetString("gridname", "the lost continent of hippo"));
@@ -123,9 +129,12 @@ namespace OpenSim.Region.DataSnapshot
123 m_period = config.Configs["DataSnapshot"].GetInt("default_snapshot_period", m_period); 129 m_period = config.Configs["DataSnapshot"].GetInt("default_snapshot_period", m_period);
124 m_maxStales = config.Configs["DataSnapshot"].GetInt("max_changes_before_update", m_maxStales); 130 m_maxStales = config.Configs["DataSnapshot"].GetInt("max_changes_before_update", m_maxStales);
125 m_snapsDir = config.Configs["DataSnapshot"].GetString("snapshot_cache_directory", m_snapsDir); 131 m_snapsDir = config.Configs["DataSnapshot"].GetString("snapshot_cache_directory", m_snapsDir);
126 m_dataServices = config.Configs["DataSnapshot"].GetString("data_services", m_dataServices);
127 m_listener_port = config.Configs["Network"].GetString("http_listener_port", m_listener_port); 132 m_listener_port = config.Configs["Network"].GetString("http_listener_port", m_listener_port);
128 133
134 m_dataServices = config.Configs["DataSnapshot"].GetString("data_services", m_dataServices);
135 // New way of spec'ing data services, one per line
136 AddDataServicesVars(config.Configs["DataSnapshot"]);
137
129 String[] annoying_string_array = config.Configs["DataSnapshot"].GetString("disable_modules", "").Split(".".ToCharArray()); 138 String[] annoying_string_array = config.Configs["DataSnapshot"].GetString("disable_modules", "").Split(".".ToCharArray());
130 foreach (String bloody_wanker in annoying_string_array) 139 foreach (String bloody_wanker in annoying_string_array)
131 { 140 {
@@ -140,8 +149,6 @@ namespace OpenSim.Region.DataSnapshot
140 return; 149 return;
141 } 150 }
142 151
143 if (m_enabled)
144 m_snapStore = new SnapshotStore(m_snapsDir, m_gridinfo, m_listener_port, m_hostname);
145 } 152 }
146 153
147 } 154 }
@@ -155,8 +162,22 @@ namespace OpenSim.Region.DataSnapshot
155 162
156 m_log.DebugFormat("[DATASNAPSHOT]: Module added to Scene {0}.", scene.RegionInfo.RegionName); 163 m_log.DebugFormat("[DATASNAPSHOT]: Module added to Scene {0}.", scene.RegionInfo.RegionName);
157 164
158 m_snapStore.AddScene(scene); 165 if (!m_servicesNotified)
166 {
167 m_hostname = scene.RegionInfo.ExternalHostName;
168 m_snapStore = new SnapshotStore(m_snapsDir, m_gridinfo, m_listener_port, m_hostname);
169
170 //Hand it the first scene, assuming that all scenes have the same BaseHTTPServer
171 new DataRequestHandler(scene, this);
172
173 if (m_dataServices != "" && m_dataServices != "noservices")
174 NotifyDataServices(m_dataServices, "online");
175
176 m_servicesNotified = true;
177 }
178
159 m_scenes.Add(scene); 179 m_scenes.Add(scene);
180 m_snapStore.AddScene(scene);
160 181
161 Assembly currentasm = Assembly.GetExecutingAssembly(); 182 Assembly currentasm = Assembly.GetExecutingAssembly();
162 183
@@ -181,22 +202,6 @@ namespace OpenSim.Region.DataSnapshot
181 } 202 }
182 } 203 }
183 204
184 // Must be done here because on shared modules, PostInitialise() will run
185 // BEFORE any scenes are registered. There is no "all scenes have been loaded"
186 // kind of callback because scenes may be created dynamically, so we cannot
187 // have that info, ever.
188 if (!m_servicesNotified)
189 {
190 //Hand it the first scene, assuming that all scenes have the same BaseHTTPServer
191 new DataRequestHandler(m_scenes[0], this);
192
193 m_hostname = m_scenes[0].RegionInfo.ExternalHostName;
194
195 if (m_dataServices != "" && m_dataServices != "noservices")
196 NotifyDataServices(m_dataServices, "online");
197
198 m_servicesNotified = true;
199 }
200 } 205 }
201 206
202 public void RemoveRegion(Scene scene) 207 public void RemoveRegion(Scene scene)
@@ -285,6 +290,28 @@ namespace OpenSim.Region.DataSnapshot
285 return null; 290 return null;
286 } 291 }
287 292
293 private void AddDataServicesVars(IConfig config)
294 {
295 // Make sure the services given this way aren't in m_dataServices already
296 List<string> servs = new List<string>(m_dataServices.Split(new char[] { ';' }));
297
298 StringBuilder sb = new StringBuilder();
299 string[] keys = config.GetKeys();
300
301 if (keys.Length > 0)
302 {
303 IEnumerable<string> serviceKeys = keys.Where(value => value.StartsWith("DATA_SRV_"));
304 foreach (string serviceKey in serviceKeys)
305 {
306 string keyValue = config.GetString(serviceKey, string.Empty).Trim();
307 if (!servs.Contains(keyValue))
308 sb.Append(keyValue).Append(";");
309 }
310 }
311
312 m_dataServices = (m_dataServices == "noservices") ? sb.ToString() : sb.Append(m_dataServices).ToString();
313 }
314
288 #endregion 315 #endregion
289 316
290 #region [Public] Snapshot storage functions 317 #region [Public] Snapshot storage functions
@@ -303,7 +330,7 @@ namespace OpenSim.Region.DataSnapshot
303 XmlNode regiondata = requestedSnap.CreateNode(XmlNodeType.Element, "regiondata", ""); 330 XmlNode regiondata = requestedSnap.CreateNode(XmlNodeType.Element, "regiondata", "");
304 try 331 try
305 { 332 {
306 if (regionName == null || regionName == "") 333 if (string.IsNullOrEmpty(regionName))
307 { 334 {
308 XmlNode timerblock = requestedSnap.CreateNode(XmlNodeType.Element, "expire", ""); 335 XmlNode timerblock = requestedSnap.CreateNode(XmlNodeType.Element, "expire", "");
309 timerblock.InnerText = m_period.ToString(); 336 timerblock.InnerText = m_period.ToString();
@@ -364,43 +391,46 @@ namespace OpenSim.Region.DataSnapshot
364 string delimStr = ";"; 391 string delimStr = ";";
365 char [] delimiter = delimStr.ToCharArray(); 392 char [] delimiter = delimStr.ToCharArray();
366 393
367 string[] services = servicesStr.Split(delimiter); 394 string[] services = servicesStr.Split(delimiter, StringSplitOptions.RemoveEmptyEntries);
368 395
369 for (int i = 0; i < services.Length; i++) 396 for (int i = 0; i < services.Length; i++)
370 { 397 {
371 string url = services[i].Trim(); 398 string url = services[i].Trim();
372 RestClient cli = new RestClient(url); 399 using (RestClient cli = new RestClient(url))
373 cli.AddQueryParameter("service", serviceName);
374 cli.AddQueryParameter("host", m_hostname);
375 cli.AddQueryParameter("port", m_listener_port);
376 cli.AddQueryParameter("secret", m_Secret.ToString());
377 cli.RequestMethod = "GET";
378 try
379 {
380 reply = cli.Request();
381 }
382 catch (WebException)
383 {
384 m_log.Warn("[DATASNAPSHOT]: Unable to notify " + url);
385 }
386 catch (Exception e)
387 {
388 m_log.Warn("[DATASNAPSHOT]: Ignoring unknown exception " + e.ToString());
389 }
390 byte[] response = new byte[1024];
391 // int n = 0;
392 try
393 { 400 {
394 // n = reply.Read(response, 0, 1024); 401 cli.AddQueryParameter("service", serviceName);
395 reply.Read(response, 0, 1024); 402 cli.AddQueryParameter("host", m_hostname);
396 } 403 cli.AddQueryParameter("port", m_listener_port);
397 catch (Exception e) 404 cli.AddQueryParameter("secret", m_Secret.ToString());
398 { 405 cli.RequestMethod = "GET";
399 m_log.WarnFormat("[DATASNAPSHOT]: Unable to decode reply from data service. Ignoring. {0}", e.StackTrace); 406 try
407 {
408 reply = cli.Request(null);
409 }
410 catch (WebException)
411 {
412 m_log.Warn("[DATASNAPSHOT]: Unable to notify " + url);
413 }
414 catch (Exception e)
415 {
416 m_log.Warn("[DATASNAPSHOT]: Ignoring unknown exception " + e.ToString());
417 }
418
419 byte[] response = new byte[1024];
420 // int n = 0;
421 try
422 {
423 // n = reply.Read(response, 0, 1024);
424 reply.Read(response, 0, 1024);
425 }
426 catch (Exception e)
427 {
428 m_log.WarnFormat("[DATASNAPSHOT]: Unable to decode reply from data service. Ignoring. {0}", e.StackTrace);
429 }
430 // This is not quite working, so...
431 // string responseStr = Util.UTF8.GetString(response);
432 m_log.Info("[DATASNAPSHOT]: data service " + url + " notified. Secret: " + m_Secret);
400 } 433 }
401 // This is not quite working, so...
402 // string responseStr = Util.UTF8.GetString(response);
403 m_log.Info("[DATASNAPSHOT]: data service " + url + " notified. Secret: " + m_Secret);
404 } 434 }
405 435
406 } 436 }
diff --git a/OpenSim/Region/DataSnapshot/EstateSnapshot.cs b/OpenSim/Region/OptionalModules/DataSnapshot/EstateSnapshot.cs
index 8da9e8c..8da9e8c 100644
--- a/OpenSim/Region/DataSnapshot/EstateSnapshot.cs
+++ b/OpenSim/Region/OptionalModules/DataSnapshot/EstateSnapshot.cs
diff --git a/OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshot.cs b/OpenSim/Region/OptionalModules/DataSnapshot/Interfaces/IDataSnapshot.cs
index 3b3db65..3b3db65 100644
--- a/OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshot.cs
+++ b/OpenSim/Region/OptionalModules/DataSnapshot/Interfaces/IDataSnapshot.cs
diff --git a/OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshotProvider.cs b/OpenSim/Region/OptionalModules/DataSnapshot/Interfaces/IDataSnapshotProvider.cs
index daea373..daea373 100644
--- a/OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshotProvider.cs
+++ b/OpenSim/Region/OptionalModules/DataSnapshot/Interfaces/IDataSnapshotProvider.cs
diff --git a/OpenSim/Region/DataSnapshot/LLSDDiscovery.cs b/OpenSim/Region/OptionalModules/DataSnapshot/LLSDDiscovery.cs
index 54a87f9..54a87f9 100644
--- a/OpenSim/Region/DataSnapshot/LLSDDiscovery.cs
+++ b/OpenSim/Region/OptionalModules/DataSnapshot/LLSDDiscovery.cs
diff --git a/OpenSim/Region/DataSnapshot/LandSnapshot.cs b/OpenSim/Region/OptionalModules/DataSnapshot/LandSnapshot.cs
index b8c90cd..b8c90cd 100644
--- a/OpenSim/Region/DataSnapshot/LandSnapshot.cs
+++ b/OpenSim/Region/OptionalModules/DataSnapshot/LandSnapshot.cs
diff --git a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs b/OpenSim/Region/OptionalModules/DataSnapshot/ObjectSnapshot.cs
index 0bb4044..0bb4044 100644
--- a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs
+++ b/OpenSim/Region/OptionalModules/DataSnapshot/ObjectSnapshot.cs
diff --git a/OpenSim/Region/DataSnapshot/SnapshotStore.cs b/OpenSim/Region/OptionalModules/DataSnapshot/SnapshotStore.cs
index aa3d2ff..480aaaf 100644
--- a/OpenSim/Region/DataSnapshot/SnapshotStore.cs
+++ b/OpenSim/Region/OptionalModules/DataSnapshot/SnapshotStore.cs
@@ -120,7 +120,7 @@ namespace OpenSim.Region.DataSnapshot
120 provider.Stale = false; 120 provider.Stale = false;
121 m_scenes[provider.GetParentScene] = true; 121 m_scenes[provider.GetParentScene] = true;
122 122
123 m_log.Info("[DATASNAPSHOT]: Generated fragment response for provider type " + provider.Name); 123 m_log.Debug("[DATASNAPSHOT]: Generated fragment response for provider type " + provider.Name);
124 } 124 }
125 else 125 else
126 { 126 {
@@ -134,7 +134,7 @@ namespace OpenSim.Region.DataSnapshot
134 data = factory.ImportNode(node, true); 134 data = factory.ImportNode(node, true);
135 } 135 }
136 136
137 m_log.Info("[DATASNAPSHOT]: Retrieved fragment response for provider type " + provider.Name); 137 m_log.Debug("[DATASNAPSHOT]: Retrieved fragment response for provider type " + provider.Name);
138 } 138 }
139 139
140 return data; 140 return data;
@@ -154,7 +154,7 @@ namespace OpenSim.Region.DataSnapshot
154 154
155 if (!m_scenes[scene]) 155 if (!m_scenes[scene])
156 { 156 {
157 m_log.Info("[DATASNAPSHOT]: Attempting to retrieve snapshot from cache."); 157 m_log.Debug("[DATASNAPSHOT]: Attempting to retrieve snapshot from cache.");
158 //get snapshot from cache 158 //get snapshot from cache
159 String path = DataFileNameScene(scene); 159 String path = DataFileNameScene(scene);
160 160
@@ -168,11 +168,11 @@ namespace OpenSim.Region.DataSnapshot
168 regionElement = factory.ImportNode(node, true); 168 regionElement = factory.ImportNode(node, true);
169 } 169 }
170 170
171 m_log.Info("[DATASNAPSHOT]: Obtained snapshot from cache for " + scene.RegionInfo.RegionName); 171 m_log.Debug("[DATASNAPSHOT]: Obtained snapshot from cache for " + scene.RegionInfo.RegionName);
172 } 172 }
173 else 173 else
174 { 174 {
175 m_log.Info("[DATASNAPSHOT]: Attempting to generate snapshot."); 175 m_log.Debug("[DATASNAPSHOT]: Attempting to generate snapshot.");
176 //make snapshot 176 //make snapshot
177 regionElement = MakeRegionNode(scene, factory); 177 regionElement = MakeRegionNode(scene, factory);
178 178
@@ -211,7 +211,7 @@ namespace OpenSim.Region.DataSnapshot
211 211
212 m_scenes[scene] = false; 212 m_scenes[scene] = false;
213 213
214 m_log.Info("[DATASNAPSHOT]: Generated new snapshot for " + scene.RegionInfo.RegionName); 214 m_log.Debug("[DATASNAPSHOT]: Generated new snapshot for " + scene.RegionInfo.RegionName);
215 } 215 }
216 216
217 return regionElement; 217 return regionElement;
diff --git a/OpenSim/Region/OptionalModules/Example/BareBonesNonShared/BareBonesNonSharedModule.cs b/OpenSim/Region/OptionalModules/Example/BareBonesNonShared/BareBonesNonSharedModule.cs
index 7d37135..bbf7168 100644
--- a/OpenSim/Region/OptionalModules/Example/BareBonesNonShared/BareBonesNonSharedModule.cs
+++ b/OpenSim/Region/OptionalModules/Example/BareBonesNonShared/BareBonesNonSharedModule.cs
@@ -33,6 +33,12 @@ using Nini.Config;
33using OpenSim.Region.Framework.Interfaces; 33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35 35
36// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
37// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
38// the available DLLs
39//[assembly: Addin("MyModule", "1.0")]
40//[assembly: AddinDependency("OpenSim", "0.8.1")]
41
36namespace OpenSim.Region.OptionalModules.Example.BareBonesNonShared 42namespace OpenSim.Region.OptionalModules.Example.BareBonesNonShared
37{ 43{
38 /// <summary> 44 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/Example/BareBonesShared/BareBonesSharedModule.cs b/OpenSim/Region/OptionalModules/Example/BareBonesShared/BareBonesSharedModule.cs
index 781fe95..46fea3e 100644
--- a/OpenSim/Region/OptionalModules/Example/BareBonesShared/BareBonesSharedModule.cs
+++ b/OpenSim/Region/OptionalModules/Example/BareBonesShared/BareBonesSharedModule.cs
@@ -33,6 +33,12 @@ using Nini.Config;
33using OpenSim.Region.Framework.Interfaces; 33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35 35
36// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
37// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
38// the available DLLs
39//[assembly: Addin("MyModule", "1.0")]
40//[assembly: AddinDependency("OpenSim", "0.8.1")]
41
36namespace OpenSim.Region.OptionalModules.Example.BareBonesShared 42namespace OpenSim.Region.OptionalModules.Example.BareBonesShared
37{ 43{
38 /// <summary> 44 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs b/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs
new file mode 100644
index 0000000..5bf0ed4
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Example/WebSocketEchoTest/WebSocketEchoModule.cs
@@ -0,0 +1,175 @@
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.Reflection;
31using OpenSim.Framework.Servers;
32using Mono.Addins;
33using log4net;
34using Nini.Config;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38using OpenSim.Framework.Servers.HttpServer;
39
40
41namespace OpenSim.Region.OptionalModules.WebSocketEchoModule
42{
43
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebSocketEchoModule")]
45 public class WebSocketEchoModule : ISharedRegionModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private bool enabled;
50 public string Name { get { return "WebSocketEchoModule"; } }
51
52 public Type ReplaceableInterface { get { return null; } }
53
54
55 private HashSet<WebSocketHttpServerHandler> _activeHandlers = new HashSet<WebSocketHttpServerHandler>();
56
57 public void Initialise(IConfigSource pConfig)
58 {
59 enabled = (pConfig.Configs["WebSocketEcho"] != null);
60// if (enabled)
61// m_log.DebugFormat("[WebSocketEchoModule]: INITIALIZED MODULE");
62 }
63
64 /// <summary>
65 /// This method sets up the callback to WebSocketHandlerCallback below when a HTTPRequest comes in for /echo
66 /// </summary>
67 public void PostInitialise()
68 {
69 if (enabled)
70 MainServer.Instance.AddWebSocketHandler("/echo", WebSocketHandlerCallback);
71 }
72
73 // This gets called by BaseHttpServer and gives us an opportunity to set things on the WebSocket handler before we turn it on
74 public void WebSocketHandlerCallback(string path, WebSocketHttpServerHandler handler)
75 {
76 SubscribeToEvents(handler);
77 handler.SetChunksize(8192);
78 handler.NoDelay_TCP_Nagle = true;
79 handler.HandshakeAndUpgrade();
80 }
81
82 //These are our normal events
83 public void SubscribeToEvents(WebSocketHttpServerHandler handler)
84 {
85 handler.OnClose += HandlerOnOnClose;
86 handler.OnText += HandlerOnOnText;
87 handler.OnUpgradeCompleted += HandlerOnOnUpgradeCompleted;
88 handler.OnData += HandlerOnOnData;
89 handler.OnPong += HandlerOnOnPong;
90 }
91
92 public void UnSubscribeToEvents(WebSocketHttpServerHandler handler)
93 {
94 handler.OnClose -= HandlerOnOnClose;
95 handler.OnText -= HandlerOnOnText;
96 handler.OnUpgradeCompleted -= HandlerOnOnUpgradeCompleted;
97 handler.OnData -= HandlerOnOnData;
98 handler.OnPong -= HandlerOnOnPong;
99 }
100
101 private void HandlerOnOnPong(object sender, PongEventArgs pongdata)
102 {
103 m_log.Info("[WebSocketEchoModule]: Got a pong.. ping time: " + pongdata.PingResponseMS);
104 }
105
106 private void HandlerOnOnData(object sender, WebsocketDataEventArgs data)
107 {
108 WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
109 obj.SendData(data.Data);
110 m_log.Info("[WebSocketEchoModule]: We received a bunch of ugly non-printable bytes");
111 obj.SendPingCheck();
112 }
113
114
115 private void HandlerOnOnUpgradeCompleted(object sender, UpgradeCompletedEventArgs completeddata)
116 {
117 WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
118 _activeHandlers.Add(obj);
119 }
120
121 private void HandlerOnOnText(object sender, WebsocketTextEventArgs text)
122 {
123 WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
124 obj.SendMessage(text.Data);
125 m_log.Info("[WebSocketEchoModule]: We received this: " + text.Data);
126 }
127
128 // Remove the references to our handler
129 private void HandlerOnOnClose(object sender, CloseEventArgs closedata)
130 {
131 WebSocketHttpServerHandler obj = sender as WebSocketHttpServerHandler;
132 UnSubscribeToEvents(obj);
133
134 lock (_activeHandlers)
135 _activeHandlers.Remove(obj);
136 obj.Dispose();
137 }
138
139 // Shutting down.. so shut down all sockets.
140 // Note.. this should be done outside of an ienumerable if you're also hook to the close event.
141 public void Close()
142 {
143 if (!enabled)
144 return;
145
146 // We convert this to a for loop so we're not in in an IEnumerable when the close
147 //call triggers an event which then removes item from _activeHandlers that we're enumerating
148 WebSocketHttpServerHandler[] items = new WebSocketHttpServerHandler[_activeHandlers.Count];
149 _activeHandlers.CopyTo(items);
150
151 for (int i = 0; i < items.Length; i++)
152 {
153 items[i].Close(string.Empty);
154 items[i].Dispose();
155 }
156 _activeHandlers.Clear();
157 MainServer.Instance.RemoveWebSocketHandler("/echo");
158 }
159
160 public void AddRegion(Scene scene)
161 {
162// m_log.DebugFormat("[WebSocketEchoModule]: REGION {0} ADDED", scene.RegionInfo.RegionName);
163 }
164
165 public void RemoveRegion(Scene scene)
166 {
167// m_log.DebugFormat("[WebSocketEchoModule]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
168 }
169
170 public void RegionLoaded(Scene scene)
171 {
172// m_log.DebugFormat("[WebSocketEchoModule]: REGION {0} LOADED", scene.RegionInfo.RegionName);
173 }
174 }
175} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
new file mode 100644
index 0000000..e95889d
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -0,0 +1,608 @@
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.IO;
31using System.Reflection;
32using System.Security.Cryptography; // for computing md5 hash
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
46
47using Ionic.Zlib;
48
49// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
50// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
51// the available DLLs
52//[assembly: Addin("MaterialsModule", "1.0")]
53//[assembly: AddinDependency("OpenSim", "0.8.1")]
54
55namespace OpenSim.Region.OptionalModules.Materials
56{
57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")]
58 public class MaterialsModule : INonSharedRegionModule
59 {
60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61
62 public string Name { get { return "MaterialsModule"; } }
63
64 public Type ReplaceableInterface { get { return null; } }
65
66 private Scene m_scene = null;
67 private bool m_enabled = false;
68 private int m_maxMaterialsPerTransaction = 50;
69
70 public Dictionary<UUID, OSDMap> m_regionMaterials = new Dictionary<UUID, OSDMap>();
71
72 public void Initialise(IConfigSource source)
73 {
74 m_enabled = true; // default is enabled
75
76 IConfig config = source.Configs["Materials"];
77 if (config != null)
78 {
79 m_enabled = config.GetBoolean("enable_materials", m_enabled);
80 m_maxMaterialsPerTransaction = config.GetInt("MaxMaterialsPerTransaction", m_maxMaterialsPerTransaction);
81 }
82
83 if (m_enabled)
84 m_log.DebugFormat("[Materials]: Initialized");
85 }
86
87 public void Close()
88 {
89 if (!m_enabled)
90 return;
91 }
92
93 public void AddRegion(Scene scene)
94 {
95 if (!m_enabled)
96 return;
97
98 m_scene = scene;
99 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
100 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
101 }
102
103 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
104 {
105 foreach (var part in obj.Parts)
106 if (part != null)
107 GetStoredMaterialsInPart(part);
108 }
109
110 private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
111 {
112 string capsBase = "/CAPS/" + caps.CapsObjectPath;
113
114 IRequestHandler renderMaterialsPostHandler
115 = new RestStreamHandler("POST", capsBase + "/",
116 (request, path, param, httpRequest, httpResponse)
117 => RenderMaterialsPostCap(request, agentID),
118 "RenderMaterials", null);
119 caps.RegisterHandler("RenderMaterials", renderMaterialsPostHandler);
120
121 // OpenSimulator CAPs infrastructure seems to be somewhat hostile towards any CAP that requires both GET
122 // and POST handlers, (at least at the time this was originally written), so we first set up a POST
123 // handler normally and then add a GET handler via MainServer
124
125 IRequestHandler renderMaterialsGetHandler
126 = new RestStreamHandler("GET", capsBase + "/",
127 (request, path, param, httpRequest, httpResponse)
128 => RenderMaterialsGetCap(request),
129 "RenderMaterials", null);
130 MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
131
132 // materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well
133 IRequestHandler renderMaterialsPutHandler
134 = new RestStreamHandler("PUT", capsBase + "/",
135 (request, path, param, httpRequest, httpResponse)
136 => RenderMaterialsPostCap(request, agentID),
137 "RenderMaterials", null);
138 MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
139 }
140
141 public void RemoveRegion(Scene scene)
142 {
143 if (!m_enabled)
144 return;
145
146 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
147 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
148 }
149
150 public void RegionLoaded(Scene scene)
151 {
152 if (!m_enabled) return;
153
154 ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
155 if (featuresModule != null)
156 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
157 }
158
159 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
160 {
161 features["MaxMaterialsPerTransaction"] = m_maxMaterialsPerTransaction;
162 }
163
164 /// <summary>
165 /// Finds any legacy materials stored in DynAttrs that may exist for this part and add them to 'm_regionMaterials'.
166 /// </summary>
167 /// <param name="part"></param>
168 private void GetLegacyStoredMaterialsInPart(SceneObjectPart part)
169 {
170 if (part.DynAttrs == null)
171 return;
172
173 OSD OSMaterials = null;
174 OSDArray matsArr = null;
175
176 lock (part.DynAttrs)
177 {
178 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
179 {
180 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
181
182 if (materialsStore == null)
183 return;
184
185 materialsStore.TryGetValue("Materials", out OSMaterials);
186 }
187
188 if (OSMaterials != null && OSMaterials is OSDArray)
189 matsArr = OSMaterials as OSDArray;
190 else
191 return;
192 }
193
194 if (matsArr == null)
195 return;
196
197 foreach (OSD elemOsd in matsArr)
198 {
199 if (elemOsd != null && elemOsd is OSDMap)
200 {
201 OSDMap matMap = elemOsd as OSDMap;
202 if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
203 {
204 try
205 {
206 lock (m_regionMaterials)
207 m_regionMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
208 }
209 catch (Exception e)
210 {
211 m_log.Warn("[Materials]: exception decoding persisted legacy material: " + e.ToString());
212 }
213 }
214 }
215 }
216 }
217
218 /// <summary>
219 /// Find the materials used in the SOP, and add them to 'm_regionMaterials'.
220 /// </summary>
221 private void GetStoredMaterialsInPart(SceneObjectPart part)
222 {
223 if (part.Shape == null)
224 return;
225
226 var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
227 if (te == null)
228 return;
229
230 GetLegacyStoredMaterialsInPart(part);
231
232 if (te.DefaultTexture != null)
233 GetStoredMaterialInFace(part, te.DefaultTexture);
234 else
235 m_log.WarnFormat(
236 "[Materials]: Default texture for part {0} (part of object {1}) in {2} unexpectedly null. Ignoring.",
237 part.Name, part.ParentGroup.Name, m_scene.Name);
238
239 foreach (Primitive.TextureEntryFace face in te.FaceTextures)
240 {
241 if (face != null)
242 GetStoredMaterialInFace(part, face);
243 }
244 }
245
246 /// <summary>
247 /// Find the materials used in one Face, and add them to 'm_regionMaterials'.
248 /// </summary>
249 private void GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face)
250 {
251 UUID id = face.MaterialID;
252 if (id == UUID.Zero)
253 return;
254
255 lock (m_regionMaterials)
256 {
257 if (m_regionMaterials.ContainsKey(id))
258 return;
259
260 byte[] data = m_scene.AssetService.GetData(id.ToString());
261 if (data == null)
262 {
263 m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id);
264 return;
265 }
266
267 OSDMap mat;
268 try
269 {
270 mat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
271 }
272 catch (Exception e)
273 {
274 m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message);
275 return;
276 }
277
278 m_regionMaterials[id] = mat;
279 }
280 }
281
282 public string RenderMaterialsPostCap(string request, UUID agentID)
283 {
284 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
285 OSDMap resp = new OSDMap();
286
287 OSDMap materialsFromViewer = null;
288
289 OSDArray respArr = new OSDArray();
290
291 if (req.ContainsKey("Zipped"))
292 {
293 OSD osd = null;
294
295 byte[] inBytes = req["Zipped"].AsBinary();
296
297 try
298 {
299 osd = ZDecompressBytesToOsd(inBytes);
300
301 if (osd != null)
302 {
303 if (osd is OSDArray) // assume array of MaterialIDs designating requested material entries
304 {
305 foreach (OSD elem in (OSDArray)osd)
306 {
307 try
308 {
309 UUID id = new UUID(elem.AsBinary(), 0);
310
311 lock (m_regionMaterials)
312 {
313 if (m_regionMaterials.ContainsKey(id))
314 {
315 OSDMap matMap = new OSDMap();
316 matMap["ID"] = OSD.FromBinary(id.GetBytes());
317 matMap["Material"] = m_regionMaterials[id];
318 respArr.Add(matMap);
319 }
320 else
321 {
322 m_log.Warn("[Materials]: request for unknown material ID: " + id.ToString());
323
324 // Theoretically we could try to load the material from the assets service,
325 // but that shouldn't be necessary because the viewer should only request
326 // materials that exist in a prim on the region, and all of these materials
327 // are already stored in m_regionMaterials.
328 }
329 }
330 }
331 catch (Exception e)
332 {
333 m_log.Error("Error getting materials in response to viewer request", e);
334 continue;
335 }
336 }
337 }
338 else if (osd is OSDMap) // request to assign a material
339 {
340 materialsFromViewer = osd as OSDMap;
341
342 if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
343 {
344 OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
345 if (matsOsd is OSDArray)
346 {
347 OSDArray matsArr = matsOsd as OSDArray;
348
349 try
350 {
351 foreach (OSDMap matsMap in matsArr)
352 {
353 uint primLocalID = 0;
354 try {
355 primLocalID = matsMap["ID"].AsUInteger();
356 }
357 catch (Exception e) {
358 m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message);
359 continue;
360 }
361
362 OSDMap mat = null;
363 try
364 {
365 mat = matsMap["Material"] as OSDMap;
366 }
367 catch (Exception e)
368 {
369 m_log.Warn("[Materials]: cannot decode \"Material\" from matsMap: " + e.Message);
370 continue;
371 }
372
373 SceneObjectPart sop = m_scene.GetSceneObjectPart(primLocalID);
374 if (sop == null)
375 {
376 m_log.WarnFormat("[Materials]: SOP not found for localId: {0}", primLocalID.ToString());
377 continue;
378 }
379
380 if (!m_scene.Permissions.CanEditObject(sop.UUID, agentID))
381 {
382 m_log.WarnFormat("User {0} can't edit object {1} {2}", agentID, sop.Name, sop.UUID);
383 continue;
384 }
385
386 Primitive.TextureEntry te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
387 if (te == null)
388 {
389 m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID);
390 continue;
391 }
392
393
394 UUID id;
395 if (mat == null)
396 {
397 // This happens then the user removes a material from a prim
398 id = UUID.Zero;
399 }
400 else
401 {
402 id = StoreMaterialAsAsset(agentID, mat, sop);
403 }
404
405
406 int face = -1;
407
408 if (matsMap.ContainsKey("Face"))
409 {
410 face = matsMap["Face"].AsInteger();
411 Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
412 faceEntry.MaterialID = id;
413 }
414 else
415 {
416 if (te.DefaultTexture == null)
417 m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
418 else
419 te.DefaultTexture.MaterialID = id;
420 }
421
422 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
423
424 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
425 sop.Shape.TextureEntry = te.GetBytes();
426
427 if (sop.ParentGroup != null)
428 {
429 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
430 sop.UpdateFlag = UpdateRequired.FULL;
431 sop.ParentGroup.HasGroupChanged = true;
432 sop.ScheduleFullUpdate();
433 }
434 }
435 }
436 catch (Exception e)
437 {
438 m_log.Warn("[Materials]: exception processing received material ", e);
439 }
440 }
441 }
442 }
443 }
444
445 }
446 catch (Exception e)
447 {
448 m_log.Warn("[Materials]: exception decoding zipped CAP payload ", e);
449 //return "";
450 }
451 }
452
453
454 resp["Zipped"] = ZCompressOSD(respArr, false);
455 string response = OSDParser.SerializeLLSDXmlString(resp);
456
457 //m_log.Debug("[Materials]: cap request: " + request);
458 //m_log.Debug("[Materials]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
459 //m_log.Debug("[Materials]: cap response: " + response);
460 return response;
461 }
462
463 private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
464 {
465 UUID id;
466 // Material UUID = hash of the material's data.
467 // This makes materials deduplicate across the entire grid (but isn't otherwise required).
468 byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
469 using (var md5 = MD5.Create())
470 id = new UUID(md5.ComputeHash(data), 0);
471
472 lock (m_regionMaterials)
473 {
474 if (!m_regionMaterials.ContainsKey(id))
475 {
476 m_regionMaterials[id] = mat;
477
478 // This asset might exist already, but it's ok to try to store it again
479 string name = "Material " + ChooseMaterialName(mat, sop);
480 name = name.Substring(0, Math.Min(64, name.Length)).Trim();
481 AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
482 asset.Data = data;
483 m_scene.AssetService.Store(asset);
484 }
485 }
486 return id;
487 }
488
489 /// <summary>
490 /// Use heuristics to choose a good name for the material.
491 /// </summary>
492 private string ChooseMaterialName(OSDMap mat, SceneObjectPart sop)
493 {
494 UUID normMap = mat["NormMap"].AsUUID();
495 if (normMap != UUID.Zero)
496 {
497 AssetBase asset = m_scene.AssetService.GetCached(normMap.ToString());
498 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
499 return asset.Name;
500 }
501
502 UUID specMap = mat["SpecMap"].AsUUID();
503 if (specMap != UUID.Zero)
504 {
505 AssetBase asset = m_scene.AssetService.GetCached(specMap.ToString());
506 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
507 return asset.Name;
508 }
509
510 if (sop.Name != "Primitive")
511 return sop.Name;
512
513 if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive"))
514 return sop.ParentGroup.Name;
515
516 return "";
517 }
518
519
520 public string RenderMaterialsGetCap(string request)
521 {
522 OSDMap resp = new OSDMap();
523 int matsCount = 0;
524 OSDArray allOsd = new OSDArray();
525
526 lock (m_regionMaterials)
527 {
528 foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials)
529 {
530 OSDMap matMap = new OSDMap();
531
532 matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
533 matMap["Material"] = kvp.Value;
534 allOsd.Add(matMap);
535 matsCount++;
536 }
537 }
538
539 resp["Zipped"] = ZCompressOSD(allOsd, false);
540
541 return OSDParser.SerializeLLSDXmlString(resp);
542 }
543
544 private static string ZippedOsdBytesToString(byte[] bytes)
545 {
546 try
547 {
548 return OSDParser.SerializeJsonString(ZDecompressBytesToOsd(bytes));
549 }
550 catch (Exception e)
551 {
552 return "ZippedOsdBytesToString caught an exception: " + e.ToString();
553 }
554 }
555
556 /// <summary>
557 /// computes a UUID by hashing a OSD object
558 /// </summary>
559 /// <param name="osd"></param>
560 /// <returns></returns>
561 private static UUID HashOsd(OSD osd)
562 {
563 byte[] data = OSDParser.SerializeLLSDBinary(osd, false);
564 using (var md5 = MD5.Create())
565 return new UUID(md5.ComputeHash(data), 0);
566 }
567
568 public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
569 {
570 OSD osd = null;
571
572 byte[] data = OSDParser.SerializeLLSDBinary(inOsd, useHeader);
573
574 using (MemoryStream msSinkCompressed = new MemoryStream())
575 {
576 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
577 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
578 {
579 zOut.Write(data, 0, data.Length);
580 }
581
582 msSinkCompressed.Seek(0L, SeekOrigin.Begin);
583 osd = OSD.FromBinary(msSinkCompressed.ToArray());
584 }
585
586 return osd;
587 }
588
589
590 public static OSD ZDecompressBytesToOsd(byte[] input)
591 {
592 OSD osd = null;
593
594 using (MemoryStream msSinkUnCompressed = new MemoryStream())
595 {
596 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
597 {
598 zOut.Write(input, 0, input.Length);
599 }
600
601 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
602 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
603 }
604
605 return osd;
606 }
607 }
608}
diff --git a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
index 40f7fbc..1d9179c 100755
--- a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
+++ b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
@@ -36,7 +36,7 @@ using OpenSim.Framework.Console;
36using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 36using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
37using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.Physics.Manager; 39using OpenSim.Region.PhysicsModules.SharedBase;
40 40
41namespace OpenSim.Region.OptionalModules.PhysicsParameters 41namespace OpenSim.Region.OptionalModules.PhysicsParameters
42{ 42{
@@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
146 { 146 {
147 foreach (PhysParameterEntry ppe in physScene.GetParameterList()) 147 foreach (PhysParameterEntry ppe in physScene.GetParameterList())
148 { 148 {
149 float val = 0.0f; 149 string val = string.Empty;
150 if (physScene.GetPhysicsParameter(ppe.name, out val)) 150 if (physScene.GetPhysicsParameter(ppe.name, out val))
151 { 151 {
152 WriteOut(" {0}/{1} = {2}", scene.RegionInfo.RegionName, ppe.name, val); 152 WriteOut(" {0}/{1} = {2}", scene.RegionInfo.RegionName, ppe.name, val);
@@ -159,7 +159,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
159 } 159 }
160 else 160 else
161 { 161 {
162 float val = 0.0f; 162 string val = string.Empty;
163 if (physScene.GetPhysicsParameter(parm, out val)) 163 if (physScene.GetPhysicsParameter(parm, out val))
164 { 164 {
165 WriteOut(" {0}/{1} = {2}", scene.RegionInfo.RegionName, parm, val); 165 WriteOut(" {0}/{1} = {2}", scene.RegionInfo.RegionName, parm, val);
@@ -185,21 +185,12 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
185 return; 185 return;
186 } 186 }
187 string parm = "xxx"; 187 string parm = "xxx";
188 float val = 0f; 188 string valparm = String.Empty;
189 uint localID = (uint)PhysParameterEntry.APPLY_TO_NONE; // set default value 189 uint localID = (uint)PhysParameterEntry.APPLY_TO_NONE; // set default value
190 try 190 try
191 { 191 {
192 parm = cmdparms[2]; 192 parm = cmdparms[2];
193 string valparm = cmdparms[3].ToLower(); 193 valparm = cmdparms[3].ToLower();
194 if (valparm == "true")
195 val = PhysParameterEntry.NUMERIC_TRUE;
196 else
197 {
198 if (valparm == "false")
199 val = PhysParameterEntry.NUMERIC_FALSE;
200 else
201 val = float.Parse(valparm, Culture.NumberFormatInfo);
202 }
203 if (cmdparms.Length > 4) 194 if (cmdparms.Length > 4)
204 { 195 {
205 if (cmdparms[4].ToLower() == "all") 196 if (cmdparms[4].ToLower() == "all")
@@ -224,7 +215,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
224 IPhysicsParameters physScene = scene.PhysicsScene as IPhysicsParameters; 215 IPhysicsParameters physScene = scene.PhysicsScene as IPhysicsParameters;
225 if (physScene != null) 216 if (physScene != null)
226 { 217 {
227 if (!physScene.SetPhysicsParameter(parm, val, localID)) 218 if (!physScene.SetPhysicsParameter(parm, valparm, localID))
228 { 219 {
229 WriteError("Failed set of parameter '{0}' for region '{1}'", parm, scene.RegionInfo.RegionName); 220 WriteError("Failed set of parameter '{0}' for region '{1}'", parm, scene.RegionInfo.RegionName);
230 } 221 }
diff --git a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs
index c1957e2..395bbf1 100644
--- a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs
+++ b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs
@@ -26,8 +26,9 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Reflection;
30using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
31using log4net; 32using log4net;
32using Mono.Addins; 33using Mono.Addins;
33using Nini.Config; 34using Nini.Config;
@@ -57,11 +58,10 @@ namespace OpenSim.Region.OptionalModules
57 58
58 public void Initialise(IConfigSource config) 59 public void Initialise(IConfigSource config)
59 { 60 {
60 IConfig myConfig = config.Configs["Startup"]; 61 string permissionModules = Util.GetConfigVarFromSections<string>(config, "permissionmodules",
62 new string[] { "Startup", "Permissions" }, "DefaultPermissionsModule");
61 63
62 string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule"); 64 List<string> modules = new List<string>(permissionModules.Split(',').Select(m => m.Trim()));
63
64 List<string> modules=new List<string>(permissionModules.Split(','));
65 65
66 if(!modules.Contains("PrimLimitsModule")) 66 if(!modules.Contains("PrimLimitsModule"))
67 return; 67 return;
@@ -102,20 +102,34 @@ namespace OpenSim.Region.OptionalModules
102 public void RegionLoaded(Scene scene) 102 public void RegionLoaded(Scene scene)
103 { 103 {
104 m_dialogModule = scene.RequestModuleInterface<IDialogModule>(); 104 m_dialogModule = scene.RequestModuleInterface<IDialogModule>();
105 } 105 }
106 106
107 private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene) 107 private bool CanRezObject(int objectCount, UUID ownerID, Vector3 objectPosition, Scene scene)
108 { 108 {
109 ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); 109 ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
110 int usedPrims = lo.PrimCounts.Total;
111 int simulatorCapacity = lo.GetSimulatorMaxPrimCount();
112 110
113 if (objectCount + usedPrims > simulatorCapacity) 111 string response = DoCommonChecks(objectCount, ownerID, lo, scene);
112
113 if (response != null)
114 { 114 {
115 m_dialogModule.SendAlertToUser(owner, "Unable to rez object because the parcel is too full"); 115 m_dialogModule.SendAlertToUser(ownerID, response);
116 return false; 116 return false;
117 } 117 }
118 return true;
119 }
118 120
121 //OnDuplicateObject
122 private bool CanDuplicateObject(int objectCount, UUID objectID, UUID ownerID, Scene scene, Vector3 objectPosition)
123 {
124 ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
125
126 string response = DoCommonChecks(objectCount, ownerID, lo, scene);
127
128 if (response != null)
129 {
130 m_dialogModule.SendAlertToUser(ownerID, response);
131 return false;
132 }
119 return true; 133 return true;
120 } 134 }
121 135
@@ -127,10 +141,12 @@ namespace OpenSim.Region.OptionalModules
127 ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y); 141 ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y);
128 ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); 142 ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y);
129 143
130 int usedPrims = newParcel.PrimCounts.Total; 144 // newParcel will be null only if it outside of our current region. If this is the case, then the
131 int simulatorCapacity = newParcel.GetSimulatorMaxPrimCount(); 145 // receiving permissions will perform the check.
132 146 if (newParcel == null)
133 // The prim hasn't crossed a region boundry so we don't need to worry 147 return true;
148
149 // The prim hasn't crossed a region boundary so we don't need to worry
134 // about prim counts here 150 // about prim counts here
135 if(oldParcel.Equals(newParcel)) 151 if(oldParcel.Equals(newParcel))
136 { 152 {
@@ -145,30 +161,53 @@ namespace OpenSim.Region.OptionalModules
145 } 161 }
146 162
147 // TODO: Add Special Case here for temporary prims 163 // TODO: Add Special Case here for temporary prims
148 164
149 if(objectCount + usedPrims > simulatorCapacity) 165 string response = DoCommonChecks(objectCount, obj.OwnerID, newParcel, scene);
166
167 if (response != null)
150 { 168 {
151 m_dialogModule.SendAlertToUser(obj.OwnerID, "Unable to move object because the destination parcel is too full"); 169 m_dialogModule.SendAlertToUser(obj.OwnerID, response);
152 return false; 170 return false;
153 } 171 }
154
155 return true; 172 return true;
156 } 173 }
157 174
158 //OnDuplicateObject 175 private string DoCommonChecks(int objectCount, UUID ownerID, ILandObject lo, Scene scene)
159 private bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition)
160 { 176 {
161 ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); 177 string response = null;
162 int usedPrims = lo.PrimCounts.Total;
163 int simulatorCapacity = lo.GetSimulatorMaxPrimCount();
164 178
165 if(objectCount + usedPrims > simulatorCapacity) 179 int simulatorCapacity = lo.GetSimulatorMaxPrimCount();
180 if ((objectCount + lo.PrimCounts.Total) > simulatorCapacity)
166 { 181 {
167 m_dialogModule.SendAlertToUser(owner, "Unable to duplicate object because the parcel is too full"); 182 response = "Unable to rez object because the parcel is too full";
168 return false;
169 } 183 }
170 184 else
171 return true; 185 {
186 int maxPrimsPerUser = scene.RegionInfo.MaxPrimsPerUser;
187 if (maxPrimsPerUser >= 0)
188 {
189 // per-user prim limit is set
190 if (ownerID != lo.LandData.OwnerID || lo.LandData.IsGroupOwned)
191 {
192 // caller is not the sole Parcel owner
193 EstateSettings estateSettings = scene.RegionInfo.EstateSettings;
194 if (ownerID != estateSettings.EstateOwner)
195 {
196 // caller is NOT the Estate owner
197 List<UUID> mgrs = new List<UUID>(estateSettings.EstateManagers);
198 if (!mgrs.Contains(ownerID))
199 {
200 // caller is not an Estate Manager
201 if ((lo.PrimCounts.Users[ownerID] + objectCount) > maxPrimsPerUser)
202 {
203 response = "Unable to rez object because you have reached your limit";
204 }
205 }
206 }
207 }
208 }
209 }
210 return response;
172 } 211 }
173 } 212 }
174} \ No newline at end of file 213}
diff --git a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
index 217b2d5..dc6ca6f 100644
--- a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
@@ -30,8 +30,8 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.7.5.*")] 33[assembly: AssemblyVersion("0.8.3.*")]
34[assembly: AssemblyFileVersion("1.0.0.0")]
35 34
36[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")] 35
37[assembly: AddinDependency("OpenSim", "0.5")] 36[assembly: Addin("OpenSim.Region.OptionalModules", OpenSim.VersionInfo.VersionNumber)]
37[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerClientEventForwarder.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerClientEventForwarder.cs
index 721d396..721d396 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerClientEventForwarder.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerClientEventForwarder.cs
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
index f424e7f..83732e2 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
@@ -51,7 +51,8 @@ namespace OpenSim.Region.RegionCombinerModule
51 m_virtScene.UnSubscribeToClientPrimEvents(client); 51 m_virtScene.UnSubscribeToClientPrimEvents(client);
52 m_virtScene.UnSubscribeToClientPrimRezEvents(client); 52 m_virtScene.UnSubscribeToClientPrimRezEvents(client);
53 m_virtScene.UnSubscribeToClientInventoryEvents(client); 53 m_virtScene.UnSubscribeToClientInventoryEvents(client);
54 ((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client); 54 if(m_virtScene.AttachmentsModule != null)
55 ((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client);
55 //m_virtScene.UnSubscribeToClientTeleportEvents(client); 56 //m_virtScene.UnSubscribeToClientTeleportEvents(client);
56 m_virtScene.UnSubscribeToClientScriptEvents(client); 57 m_virtScene.UnSubscribeToClientScriptEvents(client);
57 58
@@ -66,7 +67,8 @@ namespace OpenSim.Region.RegionCombinerModule
66 client.OnRezObject += LocalRezObject; 67 client.OnRezObject += LocalRezObject;
67 68
68 m_rootScene.SubscribeToClientInventoryEvents(client); 69 m_rootScene.SubscribeToClientInventoryEvents(client);
69 ((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client); 70 if (m_rootScene.AttachmentsModule != null)
71 ((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client);
70 //m_rootScene.SubscribeToClientTeleportEvents(client); 72 //m_rootScene.SubscribeToClientTeleportEvents(client);
71 m_rootScene.SubscribeToClientScriptEvents(client); 73 m_rootScene.SubscribeToClientScriptEvents(client);
72 74
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
index a133e51..4bf2a82 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
@@ -27,6 +27,8 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
30using OpenMetaverse; 32using OpenMetaverse;
31using OpenSim.Framework; 33using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
@@ -34,10 +36,10 @@ using OpenSim.Region.CoreModules.World.Land;
34 36
35namespace OpenSim.Region.RegionCombinerModule 37namespace OpenSim.Region.RegionCombinerModule
36{ 38{
37public class RegionCombinerLargeLandChannel : ILandChannel 39 public class RegionCombinerLargeLandChannel : ILandChannel
38 { 40 {
39 // private static readonly ILog m_log = 41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42
41 private RegionData RegData; 43 private RegionData RegData;
42 private ILandChannel RootRegionLandChannel; 44 private ILandChannel RootRegionLandChannel;
43 private readonly List<RegionData> RegionConnections; 45 private readonly List<RegionData> RegionConnections;
@@ -68,42 +70,58 @@ public class RegionCombinerLargeLandChannel : ILandChannel
68 RootRegionLandChannel.Clear(setupDefaultParcel); 70 RootRegionLandChannel.Clear(setupDefaultParcel);
69 } 71 }
70 72
71 public ILandObject GetLandObject(int x, int y) 73 public ILandObject GetLandObject(Vector3 position)
72 { 74 {
73 //m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y); 75 return GetLandObject(position.X, position.Y);
74 76 }
75 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
76 {
77 return RootRegionLandChannel.GetLandObject(x, y);
78 }
79 else
80 {
81 int offsetX = (x / (int)Constants.RegionSize);
82 int offsetY = (y / (int)Constants.RegionSize);
83 offsetX *= (int)Constants.RegionSize;
84 offsetY *= (int)Constants.RegionSize;
85 77
86 foreach (RegionData regionData in RegionConnections) 78 public ILandObject GetLandObject(int x, int y)
87 { 79 {
88 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY) 80 return GetLandObject((float)x, (float)y);
89 { 81
90 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY); 82// m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y);
91 } 83//
92 } 84// if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
93 ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene); 85// {
94 obj.LandData.Name = "NO LAND"; 86// return RootRegionLandChannel.GetLandObject(x, y);
95 return obj; 87// }
96 } 88// else
89// {
90// int offsetX = (x / (int)Constants.RegionSize);
91// int offsetY = (y / (int)Constants.RegionSize);
92// offsetX *= (int)Constants.RegionSize;
93// offsetY *= (int)Constants.RegionSize;
94//
95// foreach (RegionData regionData in RegionConnections)
96// {
97// if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
98// {
99// m_log.DebugFormat(
100// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
101// regionData.RegionScene.Name, offsetX, offsetY);
102//
103// return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
104// }
105// }
106// //ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
107// //obj.LandData.Name = "NO LAND";
108// //return obj;
109// }
110//
111// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
112//
113// return null;
97 } 114 }
98 115
99 public ILandObject GetLandObject(int localID) 116 public ILandObject GetLandObject(int localID)
100 { 117 {
118 // XXX: Possibly should be looking in every land channel, not just the root.
101 return RootRegionLandChannel.GetLandObject(localID); 119 return RootRegionLandChannel.GetLandObject(localID);
102 } 120 }
103 121
104 public ILandObject GetLandObject(float x, float y) 122 public ILandObject GetLandObject(float x, float y)
105 { 123 {
106 //m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y); 124// m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y);
107 125
108 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize) 126 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
109 { 127 {
@@ -120,14 +138,22 @@ public class RegionCombinerLargeLandChannel : ILandChannel
120 { 138 {
121 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY) 139 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
122 { 140 {
141// m_log.DebugFormat(
142// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
143// regionData.RegionScene.Name, offsetX, offsetY);
144
123 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY); 145 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
124 } 146 }
125 } 147 }
126 148
127 ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene); 149// ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
128 obj.LandData.Name = "NO LAND"; 150// obj.LandData.Name = "NO LAND";
129 return obj; 151// return obj;
130 } 152 }
153
154// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
155
156 return null;
131 } 157 }
132 158
133 public bool IsForcefulBansAllowed() 159 public bool IsForcefulBansAllowed()
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs
index 905540d..32eead0 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs
@@ -36,14 +36,16 @@ using OpenSim.Framework.Client;
36using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Framework.Console; 38using OpenSim.Framework.Console;
39using OpenSim.Region.Physics.Manager; 39using OpenSim.Region.PhysicsModules.SharedBase;
40using Mono.Addins; 40using Mono.Addins;
41 41
42namespace OpenSim.Region.RegionCombinerModule 42namespace OpenSim.Region.RegionCombinerModule
43{ 43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionCombinerModule")]
44 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule 45 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
45 { 46 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48// private static string LogHeader = "[REGION COMBINER MODULE]";
47 49
48 public string Name 50 public string Name
49 { 51 {
@@ -77,6 +79,8 @@ namespace OpenSim.Region.RegionCombinerModule
77 { 79 {
78 IConfig myConfig = source.Configs["Startup"]; 80 IConfig myConfig = source.Configs["Startup"];
79 m_combineContiguousRegions = myConfig.GetBoolean("CombineContiguousRegions", false); 81 m_combineContiguousRegions = myConfig.GetBoolean("CombineContiguousRegions", false);
82 if (m_combineContiguousRegions)
83 m_log.ErrorFormat("[REGION COMBINER MODULE]: THIS MODULE IS BEING MARKED OBSOLETE AND MAY SOON BE REMOVED. PLEASE USE VARREGIONS INSTEAD.");
80 84
81 MainConsole.Instance.Commands.AddCommand( 85 MainConsole.Instance.Commands.AddCommand(
82 "RegionCombinerModule", false, "fix-phantoms", "fix-phantoms", 86 "RegionCombinerModule", false, "fix-phantoms", "fix-phantoms",
@@ -134,6 +138,49 @@ namespace OpenSim.Region.RegionCombinerModule
134 throw new Exception(string.Format("Region with id {0} not found", regionId)); 138 throw new Exception(string.Format("Region with id {0} not found", regionId));
135 } 139 }
136 140
141 // Test to see if this postiion (relative to the region) is within the area covered
142 // by this megaregion.
143 public bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy)
144 {
145 bool ret = false;
146 if (xx < 0 || yy < 0)
147 return ret;
148
149 foreach (RegionConnections rootRegion in m_regions.Values)
150 {
151 if (currentRegion == rootRegion.RegionId)
152 {
153 // The caller is in the root region so this is an easy test
154 if (xx < rootRegion.XEnd && yy < rootRegion.YEnd)
155 {
156 ret = true;
157 }
158 break;
159 }
160 else
161 {
162 // Maybe the caller is in one of the sub-regions
163 foreach (RegionData childRegion in rootRegion.ConnectedRegions)
164 {
165 if (currentRegion == childRegion.RegionId)
166 {
167 // This is a child. Diddle the offsets and check if in
168 Vector3 positionInMegaregion = childRegion.Offset;
169 positionInMegaregion.X += xx;
170 positionInMegaregion.Y += yy;
171 if (positionInMegaregion.X < rootRegion.XEnd && positionInMegaregion.Y < rootRegion.YEnd)
172 {
173 ret = true;
174 }
175 break;
176 }
177 }
178 }
179 }
180
181 return ret;
182 }
183
137 private void NewPresence(ScenePresence presence) 184 private void NewPresence(ScenePresence presence)
138 { 185 {
139 if (presence.IsChildAgent) 186 if (presence.IsChildAgent)
@@ -220,27 +267,6 @@ namespace OpenSim.Region.RegionCombinerModule
220 // 267 //
221*/ 268*/
222 269
223 // Give each region a standard set of non-infinite borders
224 Border northBorder = new Border();
225 northBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, (int)Constants.RegionSize); //<---
226 northBorder.CrossDirection = Cardinals.N;
227 scene.NorthBorders[0] = northBorder;
228
229 Border southBorder = new Border();
230 southBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, 0); //--->
231 southBorder.CrossDirection = Cardinals.S;
232 scene.SouthBorders[0] = southBorder;
233
234 Border eastBorder = new Border();
235 eastBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, (int)Constants.RegionSize); //<---
236 eastBorder.CrossDirection = Cardinals.E;
237 scene.EastBorders[0] = eastBorder;
238
239 Border westBorder = new Border();
240 westBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, 0); //--->
241 westBorder.CrossDirection = Cardinals.W;
242 scene.WestBorders[0] = westBorder;
243
244 RegionConnections newConn = new RegionConnections(); 270 RegionConnections newConn = new RegionConnections();
245 newConn.ConnectedRegions = new List<RegionData>(); 271 newConn.ConnectedRegions = new List<RegionData>();
246 newConn.RegionScene = scene; 272 newConn.RegionScene = scene;
@@ -248,8 +274,8 @@ namespace OpenSim.Region.RegionCombinerModule
248 newConn.RegionId = scene.RegionInfo.originRegionID; 274 newConn.RegionId = scene.RegionInfo.originRegionID;
249 newConn.X = scene.RegionInfo.RegionLocX; 275 newConn.X = scene.RegionInfo.RegionLocX;
250 newConn.Y = scene.RegionInfo.RegionLocY; 276 newConn.Y = scene.RegionInfo.RegionLocY;
251 newConn.XEnd = (int)Constants.RegionSize; 277 newConn.XEnd = scene.RegionInfo.RegionSizeX;
252 newConn.YEnd = (int)Constants.RegionSize; 278 newConn.YEnd = scene.RegionInfo.RegionSizeX;
253 279
254 lock (m_regions) 280 lock (m_regions)
255 { 281 {
@@ -415,36 +441,39 @@ namespace OpenSim.Region.RegionCombinerModule
415 */ 441 */
416 #endregion 442 #endregion
417 443
418 // If we're one region over +x y 444
445 // Check to see if this new region is adjacent to the root region.
446 // Note that we expect the regions to be combined from the root region outward
447 // thus the requirement for the ordering in the configuration files.
448
449 // If we're one region over +x y (i.e. root region is to the west)
419 //xxx 450 //xxx
420 //xxy 451 //xxy
421 //xxx 452 //xxx
422
423 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY) 453 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY)
424 { 454 {
425 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene); 455 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
426 break; 456 break;
427 } 457 }
428 458
429 // If we're one region over x +y 459 // If we're one region over x +y (i.e. root region is to the south)
430 //xyx 460 //xyx
431 //xxx 461 //xxx
432 //xxx 462 //xxx
433 if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY) 463 if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
434 { 464 {
435 connectedYN = DoWorkForOneRegionOverXPlusY(rootConn, newConn, scene); 465 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
436 break; 466 break;
437 } 467 }
438 468
439 // If we're one region over +x +y 469 // If we're one region over +x +y (i.e. root region is to the south-west)
440 //xxy 470 //xxy
441 //xxx 471 //xxx
442 //xxx 472 //xxx
443 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY) 473 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
444 { 474 {
445 connectedYN = DoWorkForOneRegionOverPlusXPlusY(rootConn, newConn, scene); 475 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
446 break; 476 break;
447
448 } 477 }
449 } 478 }
450 479
@@ -454,20 +483,20 @@ namespace OpenSim.Region.RegionCombinerModule
454 DoWorkForRootRegion(newConn, scene); 483 DoWorkForRootRegion(newConn, scene);
455 } 484 }
456 } 485 }
457
458 // Set up infinite borders around the entire AABB of the combined ConnectedRegions
459 AdjustLargeRegionBounds();
460 } 486 }
461 487
462 private bool DoWorkForOneRegionOverPlusXY(RegionConnections rootConn, RegionConnections newConn, Scene scene) 488 private bool DoWorkForOneRegionOverPlusXY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
463 { 489 {
490 // Offset (in meters) from the base of this region to the base of the root region.
464 Vector3 offset = Vector3.Zero; 491 Vector3 offset = Vector3.Zero;
465 offset.X = newConn.PosX - rootConn.PosX; 492 offset.X = newConn.PosX - rootConn.PosX;
466 offset.Y = newConn.PosY - rootConn.PosY; 493 offset.Y = newConn.PosY - rootConn.PosY;
467 494
495 // The new total size of the region (in meters)
496 // We just extend the X and Y dimensions so the extent might temporarily include areas without regions.
468 Vector3 extents = Vector3.Zero; 497 Vector3 extents = Vector3.Zero;
469 extents.Y = rootConn.YEnd; 498 extents.X = Math.Max(rootConn.XEnd, offset.X + newConn.RegionScene.RegionInfo.RegionSizeX);
470 extents.X = rootConn.XEnd + newConn.XEnd; 499 extents.Y = Math.Max(rootConn.YEnd, offset.Y + newConn.RegionScene.RegionInfo.RegionSizeY);
471 500
472 rootConn.UpdateExtents(extents); 501 rootConn.UpdateExtents(extents);
473 502
@@ -476,9 +505,6 @@ namespace OpenSim.Region.RegionCombinerModule
476 rootConn.RegionScene.RegionInfo.RegionName, 505 rootConn.RegionScene.RegionInfo.RegionName,
477 newConn.RegionScene.RegionInfo.RegionName, offset, extents); 506 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
478 507
479 scene.BordersLocked = true;
480 rootConn.RegionScene.BordersLocked = true;
481
482 RegionData ConnectedRegion = new RegionData(); 508 RegionData ConnectedRegion = new RegionData();
483 ConnectedRegion.Offset = offset; 509 ConnectedRegion.Offset = offset;
484 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; 510 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -491,34 +517,10 @@ namespace OpenSim.Region.RegionCombinerModule
491 // Inform Child region that it needs to forward it's terrain to the root region 517 // Inform Child region that it needs to forward it's terrain to the root region
492 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero); 518 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
493 519
494 // Extend the borders as appropriate
495 lock (rootConn.RegionScene.EastBorders)
496 rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
497
498 lock (rootConn.RegionScene.NorthBorders)
499 rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
500
501 lock (rootConn.RegionScene.SouthBorders)
502 rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
503
504 lock (scene.WestBorders)
505 {
506 scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
507
508 // Trigger auto teleport to root region
509 scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
510 scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
511 }
512
513 // Reset Terrain.. since terrain loads before we get here, we need to load 520 // Reset Terrain.. since terrain loads before we get here, we need to load
514 // it again so it loads in the root region 521 // it again so it loads in the root region
515
516 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 522 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
517 523
518 // Unlock borders
519 rootConn.RegionScene.BordersLocked = false;
520 scene.BordersLocked = false;
521
522 // Create a client event forwarder and add this region's events to the root region. 524 // Create a client event forwarder and add this region's events to the root region.
523 if (rootConn.ClientEventForwarder != null) 525 if (rootConn.ClientEventForwarder != null)
524 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene); 526 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@@ -526,6 +528,9 @@ namespace OpenSim.Region.RegionCombinerModule
526 return true; 528 return true;
527 } 529 }
528 530
531 /*
532 * 20140215 radams1: The border stuff was removed and the addition of regions to the mega-regions
533 * was generalized. These functions are not needed for the generalized solution but left for reference.
529 private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene) 534 private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
530 { 535 {
531 Vector3 offset = Vector3.Zero; 536 Vector3 offset = Vector3.Zero;
@@ -537,9 +542,6 @@ namespace OpenSim.Region.RegionCombinerModule
537 extents.X = rootConn.XEnd; 542 extents.X = rootConn.XEnd;
538 rootConn.UpdateExtents(extents); 543 rootConn.UpdateExtents(extents);
539 544
540 scene.BordersLocked = true;
541 rootConn.RegionScene.BordersLocked = true;
542
543 RegionData ConnectedRegion = new RegionData(); 545 RegionData ConnectedRegion = new RegionData();
544 ConnectedRegion.Offset = offset; 546 ConnectedRegion.Offset = offset;
545 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; 547 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -554,30 +556,11 @@ namespace OpenSim.Region.RegionCombinerModule
554 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); 556 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
555 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero); 557 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
556 558
557 lock (rootConn.RegionScene.NorthBorders)
558 rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
559
560 lock (rootConn.RegionScene.EastBorders)
561 rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
562
563 lock (rootConn.RegionScene.WestBorders)
564 rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
565
566 lock (scene.SouthBorders)
567 {
568 scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
569 scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
570 scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
571 }
572
573 // Reset Terrain.. since terrain normally loads first. 559 // Reset Terrain.. since terrain normally loads first.
574 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); 560 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
575 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 561 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
576 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); 562 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
577 563
578 scene.BordersLocked = false;
579 rootConn.RegionScene.BordersLocked = false;
580
581 if (rootConn.ClientEventForwarder != null) 564 if (rootConn.ClientEventForwarder != null)
582 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene); 565 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
583 566
@@ -601,9 +584,6 @@ namespace OpenSim.Region.RegionCombinerModule
601 extents.Y = rootConn.YEnd; 584 extents.Y = rootConn.YEnd;
602 extents.X = rootConn.XEnd; 585 extents.X = rootConn.XEnd;
603 586
604 scene.BordersLocked = true;
605 rootConn.RegionScene.BordersLocked = true;
606
607 RegionData ConnectedRegion = new RegionData(); 587 RegionData ConnectedRegion = new RegionData();
608 ConnectedRegion.Offset = offset; 588 ConnectedRegion.Offset = offset;
609 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; 589 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -619,68 +599,10 @@ namespace OpenSim.Region.RegionCombinerModule
619 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); 599 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
620 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero); 600 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
621 601
622 lock (rootConn.RegionScene.NorthBorders)
623 {
624 if (rootConn.RegionScene.NorthBorders.Count == 1)// && 2)
625 {
626 //compound border
627 // already locked above
628 rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
629
630 lock (rootConn.RegionScene.EastBorders)
631 rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
632
633 lock (rootConn.RegionScene.WestBorders)
634 rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
635 }
636 }
637
638 lock (scene.SouthBorders)
639 {
640 scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
641 scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
642 scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
643 }
644
645 lock (rootConn.RegionScene.EastBorders)
646 {
647 if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
648 {
649
650 rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
651
652 lock (rootConn.RegionScene.NorthBorders)
653 rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
654
655 lock (rootConn.RegionScene.SouthBorders)
656 rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
657 }
658 }
659
660 lock (scene.WestBorders)
661 {
662 scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
663 scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
664 scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
665 }
666
667 /*
668 else
669 {
670 conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
671 conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
672 conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
673 scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south
674 }
675 */
676
677
678 // Reset Terrain.. since terrain normally loads first. 602 // Reset Terrain.. since terrain normally loads first.
679 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); 603 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
680 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 604 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
681 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); 605 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
682 scene.BordersLocked = false;
683 rootConn.RegionScene.BordersLocked = false;
684 606
685 if (rootConn.ClientEventForwarder != null) 607 if (rootConn.ClientEventForwarder != null)
686 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene); 608 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@@ -689,6 +611,7 @@ namespace OpenSim.Region.RegionCombinerModule
689 611
690 //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents); 612 //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
691 } 613 }
614 */
692 615
693 private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene) 616 private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene)
694 { 617 {
@@ -887,125 +810,6 @@ namespace OpenSim.Region.RegionCombinerModule
887// } 810// }
888// } 811// }
889 812
890 // Create a set of infinite borders around the whole aabb of the combined island.
891 private void AdjustLargeRegionBounds()
892 {
893 lock (m_regions)
894 {
895 foreach (RegionConnections rconn in m_regions.Values)
896 {
897 Vector3 offset = Vector3.Zero;
898 rconn.RegionScene.BordersLocked = true;
899 foreach (RegionData rdata in rconn.ConnectedRegions)
900 {
901 if (rdata.Offset.X > offset.X) offset.X = rdata.Offset.X;
902 if (rdata.Offset.Y > offset.Y) offset.Y = rdata.Offset.Y;
903 }
904
905 lock (rconn.RegionScene.NorthBorders)
906 {
907 Border northBorder = null;
908 // If we don't already have an infinite border, create one.
909 if (!TryGetInfiniteBorder(rconn.RegionScene.NorthBorders, out northBorder))
910 {
911 northBorder = new Border();
912 rconn.RegionScene.NorthBorders.Add(northBorder);
913 }
914
915 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,
916 offset.Y + (int) Constants.RegionSize); //<---
917 northBorder.CrossDirection = Cardinals.N;
918 }
919
920 lock (rconn.RegionScene.SouthBorders)
921 {
922 Border southBorder = null;
923 // If we don't already have an infinite border, create one.
924 if (!TryGetInfiniteBorder(rconn.RegionScene.SouthBorders, out southBorder))
925 {
926 southBorder = new Border();
927 rconn.RegionScene.SouthBorders.Add(southBorder);
928 }
929 southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
930 southBorder.CrossDirection = Cardinals.S;
931 }
932
933 lock (rconn.RegionScene.EastBorders)
934 {
935 Border eastBorder = null;
936 // If we don't already have an infinite border, create one.
937 if (!TryGetInfiniteBorder(rconn.RegionScene.EastBorders, out eastBorder))
938 {
939 eastBorder = new Border();
940 rconn.RegionScene.EastBorders.Add(eastBorder);
941 }
942 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, offset.X + (int)Constants.RegionSize);
943 //<---
944 eastBorder.CrossDirection = Cardinals.E;
945 }
946
947 lock (rconn.RegionScene.WestBorders)
948 {
949 Border westBorder = null;
950 // If we don't already have an infinite border, create one.
951 if (!TryGetInfiniteBorder(rconn.RegionScene.WestBorders, out westBorder))
952 {
953 westBorder = new Border();
954 rconn.RegionScene.WestBorders.Add(westBorder);
955
956 }
957 westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
958 westBorder.CrossDirection = Cardinals.W;
959 }
960
961 rconn.RegionScene.BordersLocked = false;
962 }
963 }
964 }
965
966 /// <summary>
967 /// Try and get an Infinite border out of a listT of borders
968 /// </summary>
969 /// <param name="borders"></param>
970 /// <param name="oborder"></param>
971 /// <returns></returns>
972 public static bool TryGetInfiniteBorder(List<Border> borders, out Border oborder)
973 {
974 // Warning! Should be locked before getting here!
975 foreach (Border b in borders)
976 {
977 if (b.BorderLine.X == float.MinValue && b.BorderLine.Y == float.MaxValue)
978 {
979 oborder = b;
980 return true;
981 }
982 }
983
984 oborder = null;
985 return false;
986 }
987
988 public RegionData GetRegionFromPosition(Vector3 pPosition)
989 {
990 pPosition = pPosition/(int) Constants.RegionSize;
991 int OffsetX = (int) pPosition.X;
992 int OffsetY = (int) pPosition.Y;
993
994 lock (m_regions)
995 {
996 foreach (RegionConnections regConn in m_regions.Values)
997 {
998 foreach (RegionData reg in regConn.ConnectedRegions)
999 {
1000 if (reg.Offset.X == OffsetX && reg.Offset.Y == OffsetY)
1001 return reg;
1002 }
1003 }
1004 }
1005
1006 return new RegionData();
1007 }
1008
1009 public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion) 813 public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion)
1010 { 814 {
1011 if (BigRegion.PermissionModule == null) 815 if (BigRegion.PermissionModule == null)
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerPermissionModule.cs
index 7c662c9..07dd68b 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerPermissionModule.cs
@@ -34,7 +34,7 @@ using OpenSim.Region.Framework.Scenes;
34 34
35namespace OpenSim.Region.RegionCombinerModule 35namespace OpenSim.Region.RegionCombinerModule
36{ 36{
37 public class RegionCombinerPermissionModule 37 public class RegionCombinerPermissionModule
38 { 38 {
39 private Scene m_rootScene; 39 private Scene m_rootScene;
40 40
diff --git a/OpenSim/Region/RegionCombinerModule/RegionConnections.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionConnections.cs
index fba51d2..62a3a91 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionConnections.cs
@@ -64,12 +64,12 @@ namespace OpenSim.Region.RegionCombinerModule
64 /// <summary> 64 /// <summary>
65 /// The X meters position of this connection. 65 /// The X meters position of this connection.
66 /// </summary> 66 /// </summary>
67 public uint PosX { get { return X * Constants.RegionSize; } } 67 public uint PosX { get { return Util.RegionToWorldLoc(X); } }
68 68
69 /// <summary> 69 /// <summary>
70 /// The Y meters co-ordinate of this connection. 70 /// The Y meters co-ordinate of this connection.
71 /// </summary> 71 /// </summary>
72 public uint PosY { get { return Y * Constants.RegionSize; } } 72 public uint PosY { get { return Util.RegionToWorldLoc(Y); } }
73 73
74 /// <summary> 74 /// <summary>
75 /// The size of the megaregion in meters. 75 /// The size of the megaregion in meters.
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCourseLocation.cs
index 224ac99..224ac99 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCourseLocation.cs
diff --git a/OpenSim/Region/RegionCombinerModule/RegionData.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionData.cs
index bd0e398..42fca9f 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionData.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionData.cs
@@ -34,6 +34,7 @@ namespace OpenSim.Region.RegionCombinerModule
34 { 34 {
35 public UUID RegionId; 35 public UUID RegionId;
36 public Scene RegionScene; 36 public Scene RegionScene;
37 // Offset of this region from the base of the root region.
37 public Vector3 Offset; 38 public Vector3 Offset;
38 } 39 }
39} \ No newline at end of file 40} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
index 34894ba..c38bb3e 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
49 private static readonly ILog m_log = 49 private static readonly ILog m_log =
50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 private OSD m_ValueStore; 52 protected virtual OSD ValueStore { get; set; }
53 53
54 protected class TakeValueCallbackClass 54 protected class TakeValueCallbackClass
55 { 55 {
@@ -68,42 +68,141 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
68 protected List<TakeValueCallbackClass> m_TakeStore; 68 protected List<TakeValueCallbackClass> m_TakeStore;
69 protected List<TakeValueCallbackClass> m_ReadStore; 69 protected List<TakeValueCallbackClass> m_ReadStore;
70 70
71 // add separators for quoted paths and array references
72 protected static Regex m_ParsePassOne = new Regex("({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
71 73
74 // add quotes to bare identifiers which are limited to alphabetic characters
75 protected static Regex m_ParsePassThree = new Regex("(?<!{[^}]*)\\.([a-zA-Z]+)(?=\\.)");
76
77 // remove extra separator characters
78 protected static Regex m_ParsePassFour = new Regex("\\.+");
79
80 // expression used to validate the full path, this is canonical representation
81 protected static Regex m_ValidatePath = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)*$");
82
83 // expression used to match path components
84 protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
85
86 // extract the internals of an array reference
87 protected static Regex m_SimpleArrayPattern = new Regex("^\\[([0-9]+)\\]$");
88 protected static Regex m_ArrayPattern = new Regex("^\\[([0-9]+|\\+)\\]$");
89
90 // extract the internals of a has reference
91 protected static Regex m_HashPattern = new Regex("^{([^}]+)}$");
92
93 // -----------------------------------------------------------------
94 /// <summary>
95 /// This is a simple estimator for the size of the stored data, it
96 /// is not precise, but should be close enough to implement reasonable
97 /// limits on the storage space used
98 /// </summary>
99 // -----------------------------------------------------------------
100 public int StringSpace { get; set; }
101
72 // ----------------------------------------------------------------- 102 // -----------------------------------------------------------------
73 /// <summary> 103 /// <summary>
74 /// 104 ///
75 /// </summary> 105 /// </summary>
76 // ----------------------------------------------------------------- 106 // -----------------------------------------------------------------
77 public JsonStore() : this("") {} 107 public static bool CanonicalPathExpression(string ipath, out string opath)
108 {
109 Stack<string> path;
110 if (! ParsePathExpression(ipath,out path))
111 {
112 opath = "";
113 return false;
114 }
115
116 opath = PathExpressionToKey(path);
117 return true;
118 }
78 119
79 public JsonStore(string value) 120 // -----------------------------------------------------------------
121 /// <summary>
122 ///
123 /// </summary>
124 // -----------------------------------------------------------------
125 public JsonStore()
80 { 126 {
127 StringSpace = 0;
81 m_TakeStore = new List<TakeValueCallbackClass>(); 128 m_TakeStore = new List<TakeValueCallbackClass>();
82 m_ReadStore = new List<TakeValueCallbackClass>(); 129 m_ReadStore = new List<TakeValueCallbackClass>();
83 130 }
131
132 public JsonStore(string value) : this()
133 {
134 // This is going to throw an exception if the value is not
135 // a valid JSON chunk. Calling routines should catch the
136 // exception and handle it appropriately
84 if (String.IsNullOrEmpty(value)) 137 if (String.IsNullOrEmpty(value))
85 m_ValueStore = new OSDMap(); 138 ValueStore = new OSDMap();
86 else 139 else
87 m_ValueStore = OSDParser.DeserializeJson(value); 140 ValueStore = OSDParser.DeserializeJson(value);
88 } 141 }
142
143 // -----------------------------------------------------------------
144 /// <summary>
145 ///
146 /// </summary>
147 // -----------------------------------------------------------------
148 public JsonStoreNodeType GetNodeType(string expr)
149 {
150 Stack<string> path;
151 if (! ParsePathExpression(expr,out path))
152 return JsonStoreNodeType.Undefined;
153
154 OSD result = ProcessPathExpression(ValueStore,path);
89 155
156 if (result == null)
157 return JsonStoreNodeType.Undefined;
158
159 if (result is OSDMap)
160 return JsonStoreNodeType.Object;
161
162 if (result is OSDArray)
163 return JsonStoreNodeType.Array;
164
165 if (OSDBaseType(result.Type))
166 return JsonStoreNodeType.Value;
167
168 return JsonStoreNodeType.Undefined;
169 }
170
90 // ----------------------------------------------------------------- 171 // -----------------------------------------------------------------
91 /// <summary> 172 /// <summary>
92 /// 173 ///
93 /// </summary> 174 /// </summary>
94 // ----------------------------------------------------------------- 175 // -----------------------------------------------------------------
95 public bool TestPath(string expr, bool useJson) 176 public JsonStoreValueType GetValueType(string expr)
96 { 177 {
97 Stack<string> path = ParsePathExpression(expr); 178 Stack<string> path;
98 OSD result = ProcessPathExpression(m_ValueStore,path); 179 if (! ParsePathExpression(expr,out path))
180 return JsonStoreValueType.Undefined;
181
182 OSD result = ProcessPathExpression(ValueStore,path);
99 183
100 if (result == null) 184 if (result == null)
101 return false; 185 return JsonStoreValueType.Undefined;
102 186
103 if (useJson || result.Type == OSDType.String) 187 if (result is OSDMap)
104 return true; 188 return JsonStoreValueType.Undefined;
105 189
106 return false; 190 if (result is OSDArray)
191 return JsonStoreValueType.Undefined;
192
193 if (result is OSDBoolean)
194 return JsonStoreValueType.Boolean;
195
196 if (result is OSDInteger)
197 return JsonStoreValueType.Integer;
198
199 if (result is OSDReal)
200 return JsonStoreValueType.Float;
201
202 if (result is OSDString)
203 return JsonStoreValueType.String;
204
205 return JsonStoreValueType.Undefined;
107 } 206 }
108 207
109 // ----------------------------------------------------------------- 208 // -----------------------------------------------------------------
@@ -111,10 +210,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
111 /// 210 ///
112 /// </summary> 211 /// </summary>
113 // ----------------------------------------------------------------- 212 // -----------------------------------------------------------------
213 public int ArrayLength(string expr)
214 {
215 Stack<string> path;
216 if (! ParsePathExpression(expr,out path))
217 return -1;
218
219 OSD result = ProcessPathExpression(ValueStore,path);
220 if (result != null && result.Type == OSDType.Array)
221 {
222 OSDArray arr = result as OSDArray;
223 return arr.Count;
224 }
225
226 return -1;
227 }
228
229 // -----------------------------------------------------------------
230 /// <summary>
231 ///
232 /// </summary>
233 // -----------------------------------------------------------------
114 public bool GetValue(string expr, out string value, bool useJson) 234 public bool GetValue(string expr, out string value, bool useJson)
115 { 235 {
116 Stack<string> path = ParsePathExpression(expr); 236 Stack<string> path;
117 OSD result = ProcessPathExpression(m_ValueStore,path); 237 if (! ParsePathExpression(expr,out path))
238 {
239 value = "";
240 return false;
241 }
242
243 OSD result = ProcessPathExpression(ValueStore,path);
118 return ConvertOutputValue(result,out value,useJson); 244 return ConvertOutputValue(result,out value,useJson);
119 } 245 }
120 246
@@ -136,7 +262,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
136 // ----------------------------------------------------------------- 262 // -----------------------------------------------------------------
137 public bool SetValue(string expr, string value, bool useJson) 263 public bool SetValue(string expr, string value, bool useJson)
138 { 264 {
139 OSD ovalue = useJson ? OSDParser.DeserializeJson(value) : new OSDString(value); 265 OSD ovalue;
266
267 // One note of caution... if you use an empty string in the
268 // structure it will be assumed to be a default value and will
269 // not be seialized in the json
270
271 if (useJson)
272 {
273 // There doesn't appear to be a good way to determine if the
274 // value is valid Json other than to let the parser crash
275 try
276 {
277 ovalue = OSDParser.DeserializeJson(value);
278 }
279 catch (Exception)
280 {
281 if (value.StartsWith("'") && value.EndsWith("'"))
282 {
283 ovalue = new OSDString(value.Substring(1,value.Length - 2));
284 }
285 else
286 {
287 return false;
288 }
289 }
290 }
291 else
292 {
293 ovalue = new OSDString(value);
294 }
295
140 return SetValueFromExpression(expr,ovalue); 296 return SetValueFromExpression(expr,ovalue);
141 } 297 }
142 298
@@ -147,10 +303,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
147 // ----------------------------------------------------------------- 303 // -----------------------------------------------------------------
148 public bool TakeValue(string expr, bool useJson, TakeValueCallback cback) 304 public bool TakeValue(string expr, bool useJson, TakeValueCallback cback)
149 { 305 {
150 Stack<string> path = ParsePathExpression(expr); 306 Stack<string> path;
307 if (! ParsePathExpression(expr,out path))
308 return false;
309
151 string pexpr = PathExpressionToKey(path); 310 string pexpr = PathExpressionToKey(path);
152 311
153 OSD result = ProcessPathExpression(m_ValueStore,path); 312 OSD result = ProcessPathExpression(ValueStore,path);
154 if (result == null) 313 if (result == null)
155 { 314 {
156 m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback)); 315 m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
@@ -178,10 +337,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
178 // ----------------------------------------------------------------- 337 // -----------------------------------------------------------------
179 public bool ReadValue(string expr, bool useJson, TakeValueCallback cback) 338 public bool ReadValue(string expr, bool useJson, TakeValueCallback cback)
180 { 339 {
181 Stack<string> path = ParsePathExpression(expr); 340 Stack<string> path;
341 if (! ParsePathExpression(expr,out path))
342 return false;
343
182 string pexpr = PathExpressionToKey(path); 344 string pexpr = PathExpressionToKey(path);
183 345
184 OSD result = ProcessPathExpression(m_ValueStore,path); 346 OSD result = ProcessPathExpression(ValueStore,path);
185 if (result == null) 347 if (result == null)
186 { 348 {
187 m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback)); 349 m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
@@ -208,25 +370,30 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
208 // ----------------------------------------------------------------- 370 // -----------------------------------------------------------------
209 protected bool SetValueFromExpression(string expr, OSD ovalue) 371 protected bool SetValueFromExpression(string expr, OSD ovalue)
210 { 372 {
211 Stack<string> path = ParsePathExpression(expr); 373 Stack<string> path;
374 if (! ParsePathExpression(expr,out path))
375 return false;
376
212 if (path.Count == 0) 377 if (path.Count == 0)
213 { 378 {
214 m_ValueStore = ovalue; 379 ValueStore = ovalue;
380 StringSpace = 0;
215 return true; 381 return true;
216 } 382 }
217 383
384 // pkey will be the final element in the path, we pull it out here to make sure
385 // that the assignment works correctly
218 string pkey = path.Pop(); 386 string pkey = path.Pop();
219 string pexpr = PathExpressionToKey(path); 387 string pexpr = PathExpressionToKey(path);
220 if (pexpr != "") 388 if (pexpr != "")
221 pexpr += "."; 389 pexpr += ".";
222 390
223 OSD result = ProcessPathExpression(m_ValueStore,path); 391 OSD result = ProcessPathExpression(ValueStore,path);
224 if (result == null) 392 if (result == null)
225 return false; 393 return false;
226 394
227 Regex aPattern = new Regex("\\[([0-9]+|\\+)\\]"); 395 // Check pkey, the last element in the path, for and extract array references
228 MatchCollection amatches = aPattern.Matches(pkey,0); 396 MatchCollection amatches = m_ArrayPattern.Matches(pkey,0);
229
230 if (amatches.Count > 0) 397 if (amatches.Count > 0)
231 { 398 {
232 if (result.Type != OSDType.Array) 399 if (result.Type != OSDType.Array)
@@ -242,8 +409,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
242 { 409 {
243 string npkey = String.Format("[{0}]",amap.Count); 410 string npkey = String.Format("[{0}]",amap.Count);
244 411
245 amap.Add(ovalue); 412 if (ovalue != null)
246 InvokeNextCallback(pexpr + npkey); 413 {
414 StringSpace += ComputeSizeOf(ovalue);
415
416 amap.Add(ovalue);
417 InvokeNextCallback(pexpr + npkey);
418 }
247 return true; 419 return true;
248 } 420 }
249 421
@@ -251,9 +423,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
251 if (0 <= aval && aval < amap.Count) 423 if (0 <= aval && aval < amap.Count)
252 { 424 {
253 if (ovalue == null) 425 if (ovalue == null)
426 {
427 StringSpace -= ComputeSizeOf(amap[aval]);
254 amap.RemoveAt(aval); 428 amap.RemoveAt(aval);
429 }
255 else 430 else
256 { 431 {
432 StringSpace -= ComputeSizeOf(amap[aval]);
433 StringSpace += ComputeSizeOf(ovalue);
257 amap[aval] = ovalue; 434 amap[aval] = ovalue;
258 InvokeNextCallback(pexpr + pkey); 435 InvokeNextCallback(pexpr + pkey);
259 } 436 }
@@ -263,9 +440,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
263 return false; 440 return false;
264 } 441 }
265 442
266 Regex hPattern = new Regex("{([^}]+)}"); 443 // Check for and extract hash references
267 MatchCollection hmatches = hPattern.Matches(pkey,0); 444 MatchCollection hmatches = m_HashPattern.Matches(pkey,0);
268
269 if (hmatches.Count > 0) 445 if (hmatches.Count > 0)
270 { 446 {
271 Match match = hmatches[0]; 447 Match match = hmatches[0];
@@ -274,16 +450,27 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
274 450
275 if (result is OSDMap) 451 if (result is OSDMap)
276 { 452 {
453 // this is the assignment case
277 OSDMap hmap = result as OSDMap; 454 OSDMap hmap = result as OSDMap;
278 if (ovalue != null) 455 if (ovalue != null)
279 { 456 {
457 StringSpace -= ComputeSizeOf(hmap[hkey]);
458 StringSpace += ComputeSizeOf(ovalue);
459
280 hmap[hkey] = ovalue; 460 hmap[hkey] = ovalue;
281 InvokeNextCallback(pexpr + pkey); 461 InvokeNextCallback(pexpr + pkey);
462 return true;
282 } 463 }
283 else if (hmap.ContainsKey(hkey)) 464
465 // this is the remove case
466 if (hmap.ContainsKey(hkey))
467 {
468 StringSpace -= ComputeSizeOf(hmap[hkey]);
284 hmap.Remove(hkey); 469 hmap.Remove(hkey);
285 470 return true;
286 return true; 471 }
472
473 return false;
287 } 474 }
288 475
289 return false; 476 return false;
@@ -332,39 +519,33 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
332 /// use a stack because we process the path in inverse order later 519 /// use a stack because we process the path in inverse order later
333 /// </summary> 520 /// </summary>
334 // ----------------------------------------------------------------- 521 // -----------------------------------------------------------------
335 protected static Stack<string> ParsePathExpression(string path) 522 protected static bool ParsePathExpression(string expr, out Stack<string> path)
336 { 523 {
337 Stack<string> m_path = new Stack<string>(); 524 path = new Stack<string>();
338 525
339 // add front and rear separators 526 // add front and rear separators
340 path = "." + path + "."; 527 expr = "." + expr + ".";
341 528
342 // add separators for quoted paths 529 // add separators for quoted exprs and array references
343 Regex pass1 = new Regex("{[^}]+}"); 530 expr = m_ParsePassOne.Replace(expr,".$1.",-1,0);
344 path = pass1.Replace(path,".$0.",-1,0);
345
346 // add separators for array references
347 Regex pass2 = new Regex("(\\[[0-9]+\\]|\\[\\+\\])");
348 path = pass2.Replace(path,".$0.",-1,0);
349 531
350 // add quotes to bare identifier 532 // add quotes to bare identifier
351 Regex pass3 = new Regex("\\.([a-zA-Z]+)"); 533 expr = m_ParsePassThree.Replace(expr,".{$1}",-1,0);
352 path = pass3.Replace(path,".{$1}",-1,0);
353 534
354 // remove extra separators 535 // remove extra separators
355 Regex pass4 = new Regex("\\.+"); 536 expr = m_ParsePassFour.Replace(expr,".",-1,0);
356 path = pass4.Replace(path,".",-1,0);
357 537
358 Regex validate = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$"); 538 // validate the results (catches extra quote characters for example)
359 if (validate.IsMatch(path)) 539 if (m_ValidatePath.IsMatch(expr))
360 { 540 {
361 Regex parser = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)"); 541 MatchCollection matches = m_PathComponent.Matches(expr,0);
362 MatchCollection matches = parser.Matches(path,0);
363 foreach (Match match in matches) 542 foreach (Match match in matches)
364 m_path.Push(match.Groups[1].Value); 543 path.Push(match.Groups[1].Value);
544
545 return true;
365 } 546 }
366 547
367 return m_path; 548 return false;
368 } 549 }
369 550
370 // ----------------------------------------------------------------- 551 // -----------------------------------------------------------------
@@ -385,9 +566,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
385 return null; 566 return null;
386 567
387 // ---------- Check for an array index ---------- 568 // ---------- Check for an array index ----------
388 Regex aPattern = new Regex("\\[([0-9]+)\\]"); 569 MatchCollection amatches = m_SimpleArrayPattern.Matches(pkey,0);
389 MatchCollection amatches = aPattern.Matches(pkey,0); 570
390
391 if (amatches.Count > 0) 571 if (amatches.Count > 0)
392 { 572 {
393 if (rmap.Type != OSDType.Array) 573 if (rmap.Type != OSDType.Array)
@@ -410,9 +590,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
410 } 590 }
411 591
412 // ---------- Check for a hash index ---------- 592 // ---------- Check for a hash index ----------
413 Regex hPattern = new Regex("{([^}]+)}"); 593 MatchCollection hmatches = m_HashPattern.Matches(pkey,0);
414 MatchCollection hmatches = hPattern.Matches(pkey,0); 594
415
416 if (hmatches.Count > 0) 595 if (hmatches.Count > 0)
417 { 596 {
418 if (rmap.Type != OSDType.Map) 597 if (rmap.Type != OSDType.Map)
@@ -456,14 +635,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
456 // The path pointed to an intermediate hash structure 635 // The path pointed to an intermediate hash structure
457 if (result.Type == OSDType.Map) 636 if (result.Type == OSDType.Map)
458 { 637 {
459 value = OSDParser.SerializeJsonString(result as OSDMap); 638 value = OSDParser.SerializeJsonString(result as OSDMap,true);
460 return true; 639 return true;
461 } 640 }
462 641
463 // The path pointed to an intermediate hash structure 642 // The path pointed to an intermediate hash structure
464 if (result.Type == OSDType.Array) 643 if (result.Type == OSDType.Array)
465 { 644 {
466 value = OSDParser.SerializeJsonString(result as OSDArray); 645 value = OSDParser.SerializeJsonString(result as OSDArray,true);
467 return true; 646 return true;
468 } 647 }
469 648
@@ -471,7 +650,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
471 return true; 650 return true;
472 } 651 }
473 652
474 if (result.Type == OSDType.String) 653 if (OSDBaseType(result.Type))
475 { 654 {
476 value = result.AsString(); 655 value = result.AsString();
477 return true; 656 return true;
@@ -496,5 +675,91 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
496 675
497 return pkey; 676 return pkey;
498 } 677 }
678
679 // -----------------------------------------------------------------
680 /// <summary>
681 ///
682 /// </summary>
683 // -----------------------------------------------------------------
684 protected static bool OSDBaseType(OSDType type)
685 {
686 // Should be the list of base types for which AsString() returns
687 // something useful
688 if (type == OSDType.Boolean)
689 return true;
690 if (type == OSDType.Integer)
691 return true;
692 if (type == OSDType.Real)
693 return true;
694 if (type == OSDType.String)
695 return true;
696 if (type == OSDType.UUID)
697 return true;
698 if (type == OSDType.Date)
699 return true;
700 if (type == OSDType.URI)
701 return true;
702
703 return false;
704 }
705
706 // -----------------------------------------------------------------
707 /// <summary>
708 ///
709 /// </summary>
710 // -----------------------------------------------------------------
711 protected static int ComputeSizeOf(OSD value)
712 {
713 string sval;
714
715 if (ConvertOutputValue(value,out sval,true))
716 return sval.Length;
717
718 return 0;
719 }
720 }
721
722 // -----------------------------------------------------------------
723 /// <summary>
724 /// </summary>
725 // -----------------------------------------------------------------
726 public class JsonObjectStore : JsonStore
727 {
728 private static readonly ILog m_log =
729 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
730
731 private Scene m_scene;
732 private UUID m_objectID;
733
734 protected override OSD ValueStore
735 {
736 get
737 {
738 SceneObjectPart sop = m_scene.GetSceneObjectPart(m_objectID);
739 if (sop == null)
740 {
741 // This is bad
742 return null;
743 }
744
745 return sop.DynAttrs.TopLevelMap;
746 }
747
748 // cannot set the top level
749 set
750 {
751 m_log.InfoFormat("[JsonStore] cannot set top level value in object store");
752 }
753 }
754
755 public JsonObjectStore(Scene scene, UUID oid) : base()
756 {
757 m_scene = scene;
758 m_objectID = oid;
759
760 // the size limit is imposed on whatever is already in the store
761 StringSpace = ComputeSizeOf(ValueStore);
762 }
499 } 763 }
764
500} 765}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs
new file mode 100644
index 0000000..d4b19dd
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs
@@ -0,0 +1,195 @@
1/*
2 * Copyright (c) Contributors
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 OpenSim 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 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreCommandsModule")]
48
49 public class JsonStoreCommandsModule : INonSharedRegionModule
50 {
51 private static readonly ILog m_log =
52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private IConfig m_config = null;
55 private bool m_enabled = false;
56
57 private Scene m_scene = null;
58 //private IJsonStoreModule m_store;
59 private JsonStoreModule m_store;
60
61#region Region Module interface
62
63 // -----------------------------------------------------------------
64 /// <summary>
65 /// Name of this shared module is it's class name
66 /// </summary>
67 // -----------------------------------------------------------------
68 public string Name
69 {
70 get { return this.GetType().Name; }
71 }
72
73 // -----------------------------------------------------------------
74 /// <summary>
75 /// Initialise this shared module
76 /// </summary>
77 /// <param name="scene">this region is getting initialised</param>
78 /// <param name="source">nini config, we are not using this</param>
79 // -----------------------------------------------------------------
80 public void Initialise(IConfigSource config)
81 {
82 try
83 {
84 if ((m_config = config.Configs["JsonStore"]) == null)
85 {
86 // There is no configuration, the module is disabled
87 // m_log.InfoFormat("[JsonStore] no configuration info");
88 return;
89 }
90
91 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
92 }
93 catch (Exception e)
94 {
95 m_log.Error("[JsonStore]: initialization error: {0}", e);
96 return;
97 }
98
99 if (m_enabled)
100 m_log.DebugFormat("[JsonStore]: module is enabled");
101 }
102
103 // -----------------------------------------------------------------
104 /// <summary>
105 /// everything is loaded, perform post load configuration
106 /// </summary>
107 // -----------------------------------------------------------------
108 public void PostInitialise()
109 {
110 }
111
112 // -----------------------------------------------------------------
113 /// <summary>
114 /// Nothing to do on close
115 /// </summary>
116 // -----------------------------------------------------------------
117 public void Close()
118 {
119 }
120
121 // -----------------------------------------------------------------
122 /// <summary>
123 /// </summary>
124 // -----------------------------------------------------------------
125 public void AddRegion(Scene scene)
126 {
127 if (m_enabled)
128 {
129 m_scene = scene;
130
131 }
132 }
133
134 // -----------------------------------------------------------------
135 /// <summary>
136 /// </summary>
137 // -----------------------------------------------------------------
138 public void RemoveRegion(Scene scene)
139 {
140 // need to remove all references to the scene in the subscription
141 // list to enable full garbage collection of the scene object
142 }
143
144 // -----------------------------------------------------------------
145 /// <summary>
146 /// Called when all modules have been added for a region. This is
147 /// where we hook up events
148 /// </summary>
149 // -----------------------------------------------------------------
150 public void RegionLoaded(Scene scene)
151 {
152 if (m_enabled)
153 {
154 m_scene = scene;
155
156 m_store = (JsonStoreModule) m_scene.RequestModuleInterface<IJsonStoreModule>();
157 if (m_store == null)
158 {
159 m_log.ErrorFormat("[JsonStoreCommands]: JsonModule interface not defined");
160 m_enabled = false;
161 return;
162 }
163
164 scene.AddCommand("JsonStore", this, "jsonstore stats", "jsonstore stats",
165 "Display statistics about the state of the JsonStore module", "",
166 CmdStats);
167 }
168 }
169
170 /// -----------------------------------------------------------------
171 /// <summary>
172 /// </summary>
173 // -----------------------------------------------------------------
174 public Type ReplaceableInterface
175 {
176 get { return null; }
177 }
178
179#endregion
180
181#region Commands
182
183 private void CmdStats(string module, string[] cmd)
184 {
185 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
186 return;
187
188 JsonStoreStats stats = m_store.GetStoreStats();
189 MainConsole.Instance.OutputFormat("{0}\t{1}",m_scene.RegionInfo.RegionName,stats.StoreCount);
190 }
191
192#endregion
193
194 }
195}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
index e68764a..26044f0 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -42,7 +42,6 @@ using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic; 42using System.Collections.Generic;
43using System.Text.RegularExpressions; 43using System.Text.RegularExpressions;
44 44
45
46namespace OpenSim.Region.OptionalModules.Scripting.JsonStore 45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
47{ 46{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")] 47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")]
@@ -54,9 +53,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
54 53
55 private IConfig m_config = null; 54 private IConfig m_config = null;
56 private bool m_enabled = false; 55 private bool m_enabled = false;
56 private bool m_enableObjectStore = false;
57 private int m_maxStringSpace = Int32.MaxValue;
58
57 private Scene m_scene = null; 59 private Scene m_scene = null;
58 60
59 private Dictionary<UUID,JsonStore> m_JsonValueStore; 61 private Dictionary<UUID,JsonStore> m_JsonValueStore;
62
60 private UUID m_sharedStore; 63 private UUID m_sharedStore;
61 64
62#region Region Module interface 65#region Region Module interface
@@ -90,15 +93,19 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
90 } 93 }
91 94
92 m_enabled = m_config.GetBoolean("Enabled", m_enabled); 95 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
96 m_enableObjectStore = m_config.GetBoolean("EnableObjectStore", m_enableObjectStore);
97 m_maxStringSpace = m_config.GetInt("MaxStringSpace", m_maxStringSpace);
98 if (m_maxStringSpace == 0)
99 m_maxStringSpace = Int32.MaxValue;
93 } 100 }
94 catch (Exception e) 101 catch (Exception e)
95 { 102 {
96 m_log.ErrorFormat("[JsonStore] initialization error: {0}",e.Message); 103 m_log.Error("[JsonStore]: initialization error: {0}", e);
97 return; 104 return;
98 } 105 }
99 106
100 if (m_enabled) 107 if (m_enabled)
101 m_log.DebugFormat("[JsonStore] module is enabled"); 108 m_log.DebugFormat("[JsonStore]: module is enabled");
102 } 109 }
103 110
104 // ----------------------------------------------------------------- 111 // -----------------------------------------------------------------
@@ -133,6 +140,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
133 m_sharedStore = UUID.Zero; 140 m_sharedStore = UUID.Zero;
134 m_JsonValueStore = new Dictionary<UUID,JsonStore>(); 141 m_JsonValueStore = new Dictionary<UUID,JsonStore>();
135 m_JsonValueStore.Add(m_sharedStore,new JsonStore("")); 142 m_JsonValueStore.Add(m_sharedStore,new JsonStore(""));
143
144 scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene;
136 } 145 }
137 } 146 }
138 147
@@ -142,6 +151,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
142 // ----------------------------------------------------------------- 151 // -----------------------------------------------------------------
143 public void RemoveRegion(Scene scene) 152 public void RemoveRegion(Scene scene)
144 { 153 {
154 scene.EventManager.OnObjectBeingRemovedFromScene -= EventManagerOnObjectBeingRemovedFromScene;
155
145 // need to remove all references to the scene in the subscription 156 // need to remove all references to the scene in the subscription
146 // list to enable full garbage collection of the scene object 157 // list to enable full garbage collection of the scene object
147 } 158 }
@@ -154,7 +165,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
154 // ----------------------------------------------------------------- 165 // -----------------------------------------------------------------
155 public void RegionLoaded(Scene scene) 166 public void RegionLoaded(Scene scene)
156 { 167 {
157 if (m_enabled) {} 168 if (m_enabled)
169 {
170 }
158 } 171 }
159 172
160 /// ----------------------------------------------------------------- 173 /// -----------------------------------------------------------------
@@ -168,8 +181,68 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
168 181
169#endregion 182#endregion
170 183
184#region SceneEvents
185 // -----------------------------------------------------------------
186 /// <summary>
187 ///
188 /// </summary>
189 // -----------------------------------------------------------------
190 public void EventManagerOnObjectBeingRemovedFromScene(SceneObjectGroup obj)
191 {
192 obj.ForEachPart(delegate(SceneObjectPart sop) { DestroyStore(sop.UUID); } );
193 }
194
195#endregion
196
171#region ScriptInvocationInteface 197#region ScriptInvocationInteface
172 198
199
200 // -----------------------------------------------------------------
201 /// <summary>
202 ///
203 /// </summary>
204 // -----------------------------------------------------------------
205 public JsonStoreStats GetStoreStats()
206 {
207 JsonStoreStats stats;
208
209 lock (m_JsonValueStore)
210 {
211 stats.StoreCount = m_JsonValueStore.Count;
212 }
213
214 return stats;
215 }
216
217 // -----------------------------------------------------------------
218 /// <summary>
219 ///
220 /// </summary>
221 // -----------------------------------------------------------------
222 public bool AttachObjectStore(UUID objectID)
223 {
224 if (! m_enabled) return false;
225 if (! m_enableObjectStore) return false;
226
227 SceneObjectPart sop = m_scene.GetSceneObjectPart(objectID);
228 if (sop == null)
229 {
230 m_log.ErrorFormat("[JsonStore] unable to attach to unknown object; {0}", objectID);
231 return false;
232 }
233
234 lock (m_JsonValueStore)
235 {
236 if (m_JsonValueStore.ContainsKey(objectID))
237 return true;
238
239 JsonStore map = new JsonObjectStore(m_scene,objectID);
240 m_JsonValueStore.Add(objectID,map);
241 }
242
243 return true;
244 }
245
173 // ----------------------------------------------------------------- 246 // -----------------------------------------------------------------
174 /// <summary> 247 /// <summary>
175 /// 248 ///
@@ -189,9 +262,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
189 { 262 {
190 map = new JsonStore(value); 263 map = new JsonStore(value);
191 } 264 }
192 catch (Exception e) 265 catch (Exception)
193 { 266 {
194 m_log.InfoFormat("[JsonStore] Unable to initialize store from {0}; {1}",value,e.Message); 267 m_log.ErrorFormat("[JsonStore]: Unable to initialize store from {0}", value);
195 return false; 268 return false;
196 } 269 }
197 270
@@ -211,9 +284,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
211 if (! m_enabled) return false; 284 if (! m_enabled) return false;
212 285
213 lock (m_JsonValueStore) 286 lock (m_JsonValueStore)
214 m_JsonValueStore.Remove(storeID); 287 return m_JsonValueStore.Remove(storeID);
215
216 return true;
217 } 288 }
218 289
219 // ----------------------------------------------------------------- 290 // -----------------------------------------------------------------
@@ -221,31 +292,76 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
221 /// 292 ///
222 /// </summary> 293 /// </summary>
223 // ----------------------------------------------------------------- 294 // -----------------------------------------------------------------
224 public bool TestPath(UUID storeID, string path, bool useJson) 295 public bool TestStore(UUID storeID)
225 { 296 {
226 if (! m_enabled) return false; 297 if (! m_enabled) return false;
227 298
299 lock (m_JsonValueStore)
300 return m_JsonValueStore.ContainsKey(storeID);
301 }
302
303 // -----------------------------------------------------------------
304 /// <summary>
305 ///
306 /// </summary>
307 // -----------------------------------------------------------------
308 public JsonStoreNodeType GetNodeType(UUID storeID, string path)
309 {
310 if (! m_enabled) return JsonStoreNodeType.Undefined;
311
228 JsonStore map = null; 312 JsonStore map = null;
229 lock (m_JsonValueStore) 313 lock (m_JsonValueStore)
230 { 314 {
231 if (! m_JsonValueStore.TryGetValue(storeID,out map)) 315 if (! m_JsonValueStore.TryGetValue(storeID,out map))
232 { 316 {
233 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); 317 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
234 return false; 318 return JsonStoreNodeType.Undefined;
235 } 319 }
236 } 320 }
237 321
238 try 322 try
239 { 323 {
240 lock (map) 324 lock (map)
241 return map.TestPath(path,useJson); 325 return map.GetNodeType(path);
242 } 326 }
243 catch (Exception e) 327 catch (Exception e)
244 { 328 {
245 m_log.InfoFormat("[JsonStore] Path test failed for {0} in {1}; {2}",path,storeID,e.Message); 329 m_log.Error(string.Format("[JsonStore]: Path test failed for {0} in {1}", path, storeID), e);
246 } 330 }
247 331
248 return false; 332 return JsonStoreNodeType.Undefined;
333 }
334
335 // -----------------------------------------------------------------
336 /// <summary>
337 ///
338 /// </summary>
339 // -----------------------------------------------------------------
340 public JsonStoreValueType GetValueType(UUID storeID, string path)
341 {
342 if (! m_enabled) return JsonStoreValueType.Undefined;
343
344 JsonStore map = null;
345 lock (m_JsonValueStore)
346 {
347 if (! m_JsonValueStore.TryGetValue(storeID,out map))
348 {
349 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
350 return JsonStoreValueType.Undefined;
351 }
352 }
353
354 try
355 {
356 lock (map)
357 return map.GetValueType(path);
358 }
359 catch (Exception e)
360 {
361 m_log.Error(string.Format("[JsonStore]: Path test failed for {0} in {1}", path, storeID), e);
362 }
363
364 return JsonStoreValueType.Undefined;
249 } 365 }
250 366
251 // ----------------------------------------------------------------- 367 // -----------------------------------------------------------------
@@ -270,12 +386,20 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
270 try 386 try
271 { 387 {
272 lock (map) 388 lock (map)
273 if (map.SetValue(path,value,useJson)) 389 {
274 return true; 390 if (map.StringSpace > m_maxStringSpace)
391 {
392 m_log.WarnFormat("[JsonStore] {0} exceeded string size; {1} bytes used of {2} limit",
393 storeID,map.StringSpace,m_maxStringSpace);
394 return false;
395 }
396
397 return map.SetValue(path,value,useJson);
398 }
275 } 399 }
276 catch (Exception e) 400 catch (Exception e)
277 { 401 {
278 m_log.InfoFormat("[JsonStore] Unable to assign {0} to {1} in {2}; {3}",value,path,storeID,e.Message); 402 m_log.Error(string.Format("[JsonStore]: Unable to assign {0} to {1} in {2}", value, path, storeID), e);
279 } 403 }
280 404
281 return false; 405 return false;
@@ -303,12 +427,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
303 try 427 try
304 { 428 {
305 lock (map) 429 lock (map)
306 if (map.RemoveValue(path)) 430 return map.RemoveValue(path);
307 return true;
308 } 431 }
309 catch (Exception e) 432 catch (Exception e)
310 { 433 {
311 m_log.InfoFormat("[JsonStore] Unable to remove {0} in {1}; {2}",path,storeID,e.Message); 434 m_log.Error(string.Format("[JsonStore]: Unable to remove {0} in {1}", path, storeID), e);
312 } 435 }
313 436
314 return false; 437 return false;
@@ -319,6 +442,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
319 /// 442 ///
320 /// </summary> 443 /// </summary>
321 // ----------------------------------------------------------------- 444 // -----------------------------------------------------------------
445 public int GetArrayLength(UUID storeID, string path)
446 {
447 if (! m_enabled) return -1;
448
449 JsonStore map = null;
450 lock (m_JsonValueStore)
451 {
452 if (! m_JsonValueStore.TryGetValue(storeID,out map))
453 return -1;
454 }
455
456 try
457 {
458 lock (map)
459 {
460 return map.ArrayLength(path);
461 }
462 }
463 catch (Exception e)
464 {
465 m_log.Error("[JsonStore]: unable to retrieve value", e);
466 }
467
468 return -1;
469 }
470
471 // -----------------------------------------------------------------
472 /// <summary>
473 ///
474 /// </summary>
475 // -----------------------------------------------------------------
322 public bool GetValue(UUID storeID, string path, bool useJson, out string value) 476 public bool GetValue(UUID storeID, string path, bool useJson, out string value)
323 { 477 {
324 value = String.Empty; 478 value = String.Empty;
@@ -341,7 +495,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
341 } 495 }
342 catch (Exception e) 496 catch (Exception e)
343 { 497 {
344 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.Message); 498 m_log.Error("[JsonStore]: unable to retrieve value", e);
345 } 499 }
346 500
347 return false; 501 return false;
@@ -380,7 +534,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
380 } 534 }
381 catch (Exception e) 535 catch (Exception e)
382 { 536 {
383 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString()); 537 m_log.Error("[JsonStore] unable to retrieve value", e);
384 } 538 }
385 539
386 cback(String.Empty); 540 cback(String.Empty);
@@ -419,7 +573,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
419 } 573 }
420 catch (Exception e) 574 catch (Exception e)
421 { 575 {
422 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString()); 576 m_log.Error("[JsonStore]: unable to retrieve value", e);
423 } 577 }
424 578
425 cback(String.Empty); 579 cback(String.Empty);
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
index 0c175ca..edf51a2 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -39,8 +39,10 @@ using OpenMetaverse.StructuredData;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.Framework.Scenes.Scripting;
42using System.Collections.Generic; 43using System.Collections.Generic;
43using System.Text.RegularExpressions; 44using System.Text.RegularExpressions;
45using PermissionMask = OpenSim.Framework.PermissionMask;
44 46
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore 47namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{ 48{
@@ -57,7 +59,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
57 59
58 private IScriptModuleComms m_comms; 60 private IScriptModuleComms m_comms;
59 private IJsonStoreModule m_store; 61 private IJsonStoreModule m_store;
60 62
63 private Dictionary<UUID,HashSet<UUID>> m_scriptStores = new Dictionary<UUID,HashSet<UUID>>();
64
61#region Region Module interface 65#region Region Module interface
62 66
63 // ----------------------------------------------------------------- 67 // -----------------------------------------------------------------
@@ -92,12 +96,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
92 } 96 }
93 catch (Exception e) 97 catch (Exception e)
94 { 98 {
95 m_log.ErrorFormat("[JsonStoreScripts] initialization error: {0}",e.Message); 99 m_log.ErrorFormat("[JsonStoreScripts]: initialization error: {0}", e.Message);
96 return; 100 return;
97 } 101 }
98 102
99 if (m_enabled) 103 if (m_enabled)
100 m_log.DebugFormat("[JsonStoreScripts] module is enabled"); 104 m_log.DebugFormat("[JsonStoreScripts]: module is enabled");
101 } 105 }
102 106
103 // ----------------------------------------------------------------- 107 // -----------------------------------------------------------------
@@ -124,6 +128,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
124 // ----------------------------------------------------------------- 128 // -----------------------------------------------------------------
125 public void AddRegion(Scene scene) 129 public void AddRegion(Scene scene)
126 { 130 {
131 scene.EventManager.OnScriptReset += HandleScriptReset;
132 scene.EventManager.OnRemoveScript += HandleScriptReset;
127 } 133 }
128 134
129 // ----------------------------------------------------------------- 135 // -----------------------------------------------------------------
@@ -132,12 +138,34 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
132 // ----------------------------------------------------------------- 138 // -----------------------------------------------------------------
133 public void RemoveRegion(Scene scene) 139 public void RemoveRegion(Scene scene)
134 { 140 {
141 scene.EventManager.OnScriptReset -= HandleScriptReset;
142 scene.EventManager.OnRemoveScript -= HandleScriptReset;
143
135 // need to remove all references to the scene in the subscription 144 // need to remove all references to the scene in the subscription
136 // list to enable full garbage collection of the scene object 145 // list to enable full garbage collection of the scene object
137 } 146 }
138 147
139 // ----------------------------------------------------------------- 148 // -----------------------------------------------------------------
140 /// <summary> 149 /// <summary>
150 /// </summary>
151 // -----------------------------------------------------------------
152 private void HandleScriptReset(uint localID, UUID itemID)
153 {
154 HashSet<UUID> stores;
155
156 lock (m_scriptStores)
157 {
158 if (! m_scriptStores.TryGetValue(itemID, out stores))
159 return;
160 m_scriptStores.Remove(itemID);
161 }
162
163 foreach (UUID id in stores)
164 m_store.DestroyStore(id);
165 }
166
167 // -----------------------------------------------------------------
168 /// <summary>
141 /// Called when all modules have been added for a region. This is 169 /// Called when all modules have been added for a region. This is
142 /// where we hook up events 170 /// where we hook up events
143 /// </summary> 171 /// </summary>
@@ -150,7 +178,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
150 m_comms = m_scene.RequestModuleInterface<IScriptModuleComms>(); 178 m_comms = m_scene.RequestModuleInterface<IScriptModuleComms>();
151 if (m_comms == null) 179 if (m_comms == null)
152 { 180 {
153 m_log.ErrorFormat("[JsonStoreScripts] ScriptModuleComms interface not defined"); 181 m_log.ErrorFormat("[JsonStoreScripts]: ScriptModuleComms interface not defined");
154 m_enabled = false; 182 m_enabled = false;
155 return; 183 return;
156 } 184 }
@@ -158,40 +186,20 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
158 m_store = m_scene.RequestModuleInterface<IJsonStoreModule>(); 186 m_store = m_scene.RequestModuleInterface<IJsonStoreModule>();
159 if (m_store == null) 187 if (m_store == null)
160 { 188 {
161 m_log.ErrorFormat("[JsonStoreScripts] JsonModule interface not defined"); 189 m_log.ErrorFormat("[JsonStoreScripts]: JsonModule interface not defined");
162 m_enabled = false; 190 m_enabled = false;
163 return; 191 return;
164 } 192 }
165 193
166 try 194 try
167 { 195 {
168 m_comms.RegisterScriptInvocation(this,"JsonCreateStore"); 196 m_comms.RegisterScriptInvocations(this);
169 m_comms.RegisterScriptInvocation(this,"JsonDestroyStore"); 197 m_comms.RegisterConstants(this);
170
171 m_comms.RegisterScriptInvocation(this,"JsonReadNotecard");
172 m_comms.RegisterScriptInvocation(this,"JsonWriteNotecard");
173
174 m_comms.RegisterScriptInvocation(this,"JsonTestPath");
175 m_comms.RegisterScriptInvocation(this,"JsonTestPathJson");
176
177 m_comms.RegisterScriptInvocation(this,"JsonGetValue");
178 m_comms.RegisterScriptInvocation(this,"JsonGetValueJson");
179
180 m_comms.RegisterScriptInvocation(this,"JsonTakeValue");
181 m_comms.RegisterScriptInvocation(this,"JsonTakeValueJson");
182
183 m_comms.RegisterScriptInvocation(this,"JsonReadValue");
184 m_comms.RegisterScriptInvocation(this,"JsonReadValueJson");
185
186 m_comms.RegisterScriptInvocation(this,"JsonSetValue");
187 m_comms.RegisterScriptInvocation(this,"JsonSetValueJson");
188
189 m_comms.RegisterScriptInvocation(this,"JsonRemoveValue");
190 } 198 }
191 catch (Exception e) 199 catch (Exception e)
192 { 200 {
193 // See http://opensimulator.org/mantis/view.php?id=5971 for more information 201 // See http://opensimulator.org/mantis/view.php?id=5971 for more information
194 m_log.WarnFormat("[JsonStroreScripts] script method registration failed; {0}",e.Message); 202 m_log.WarnFormat("[JsonStoreScripts]: script method registration failed; {0}", e.Message);
195 m_enabled = false; 203 m_enabled = false;
196 } 204 }
197 } 205 }
@@ -208,28 +216,73 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
208 216
209#endregion 217#endregion
210 218
219#region ScriptConstantsInterface
220
221 [ScriptConstant]
222 public static readonly int JSON_NODETYPE_UNDEF = (int)JsonStoreNodeType.Undefined;
223
224 [ScriptConstant]
225 public static readonly int JSON_NODETYPE_OBJECT = (int)JsonStoreNodeType.Object;
226
227 [ScriptConstant]
228 public static readonly int JSON_NODETYPE_ARRAY = (int)JsonStoreNodeType.Array;
229
230 [ScriptConstant]
231 public static readonly int JSON_NODETYPE_VALUE = (int)JsonStoreNodeType.Value;
232
233 [ScriptConstant]
234 public static readonly int JSON_VALUETYPE_UNDEF = (int)JsonStoreValueType.Undefined;
235
236 [ScriptConstant]
237 public static readonly int JSON_VALUETYPE_BOOLEAN = (int)JsonStoreValueType.Boolean;
238
239 [ScriptConstant]
240 public static readonly int JSON_VALUETYPE_INTEGER = (int)JsonStoreValueType.Integer;
241
242 [ScriptConstant]
243 public static readonly int JSON_VALUETYPE_FLOAT = (int)JsonStoreValueType.Float;
244
245 [ScriptConstant]
246 public static readonly int JSON_VALUETYPE_STRING = (int)JsonStoreValueType.String;
247
248
249#endregion
250
211#region ScriptInvocationInteface 251#region ScriptInvocationInteface
212 // ----------------------------------------------------------------- 252 // -----------------------------------------------------------------
213 /// <summary> 253 /// <summary>
214 /// 254 ///
215 /// </summary> 255 /// </summary>
216 // ----------------------------------------------------------------- 256 // -----------------------------------------------------------------
217 protected void GenerateRuntimeError(string msg) 257 [ScriptInvocation]
258 public UUID JsonAttachObjectStore(UUID hostID, UUID scriptID)
218 { 259 {
219 throw new Exception("JsonStore Runtime Error: " + msg); 260 UUID uuid = UUID.Zero;
261 if (! m_store.AttachObjectStore(hostID))
262 GenerateRuntimeError("Failed to create Json store");
263
264 return hostID;
220 } 265 }
221 266
222 // ----------------------------------------------------------------- 267 // -----------------------------------------------------------------
223 /// <summary> 268 /// <summary>
224 /// 269 ///
225 /// </summary> 270 /// </summary>
226 // ----------------------------------------------------------------- 271 // -----------------------------------------------------------------
227 protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) 272 [ScriptInvocation]
273 public UUID JsonCreateStore(UUID hostID, UUID scriptID, string value)
228 { 274 {
229 UUID uuid = UUID.Zero; 275 UUID uuid = UUID.Zero;
230 if (! m_store.CreateStore(value, ref uuid)) 276 if (! m_store.CreateStore(value, ref uuid))
231 GenerateRuntimeError("Failed to create Json store"); 277 GenerateRuntimeError("Failed to create Json store");
232 278
279 lock (m_scriptStores)
280 {
281 if (! m_scriptStores.ContainsKey(scriptID))
282 m_scriptStores[scriptID] = new HashSet<UUID>();
283
284 m_scriptStores[scriptID].Add(uuid);
285 }
233 return uuid; 286 return uuid;
234 } 287 }
235 288
@@ -238,8 +291,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
238 /// 291 ///
239 /// </summary> 292 /// </summary>
240 // ----------------------------------------------------------------- 293 // -----------------------------------------------------------------
241 protected int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID) 294 [ScriptInvocation]
295 public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID)
242 { 296 {
297 lock(m_scriptStores)
298 {
299 if (m_scriptStores.ContainsKey(scriptID))
300 m_scriptStores[scriptID].Remove(storeID);
301 }
302
243 return m_store.DestroyStore(storeID) ? 1 : 0; 303 return m_store.DestroyStore(storeID) ? 1 : 0;
244 } 304 }
245 305
@@ -248,10 +308,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
248 /// 308 ///
249 /// </summary> 309 /// </summary>
250 // ----------------------------------------------------------------- 310 // -----------------------------------------------------------------
251 protected UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID) 311 [ScriptInvocation]
312 public int JsonTestStore(UUID hostID, UUID scriptID, UUID storeID)
313 {
314 return m_store.TestStore(storeID) ? 1 : 0;
315 }
316
317 // -----------------------------------------------------------------
318 /// <summary>
319 ///
320 /// </summary>
321 // -----------------------------------------------------------------
322 [ScriptInvocation]
323 public UUID JsonRezAtRoot(UUID hostID, UUID scriptID, string item, Vector3 pos, Vector3 vel, Quaternion rot, string param)
324 {
325 UUID reqID = UUID.Random();
326 Util.FireAndForget(
327 o => DoJsonRezObject(hostID, scriptID, reqID, item, pos, vel, rot, param), null, "JsonStoreScriptModule.DoJsonRezObject");
328 return reqID;
329 }
330
331 // -----------------------------------------------------------------
332 /// <summary>
333 ///
334 /// </summary>
335 // -----------------------------------------------------------------
336 [ScriptInvocation]
337 public UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string notecardIdentifier)
252 { 338 {
253 UUID reqID = UUID.Random(); 339 UUID reqID = UUID.Random();
254 Util.FireAndForget(delegate(object o) { DoJsonReadNotecard(reqID,hostID,scriptID,storeID,path,assetID); }); 340 Util.FireAndForget(
341 o => DoJsonReadNotecard(reqID, hostID, scriptID, storeID, path, notecardIdentifier), null, "JsonStoreScriptModule.JsonReadNotecard");
255 return reqID; 342 return reqID;
256 } 343 }
257 344
@@ -260,10 +347,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
260 /// 347 ///
261 /// </summary> 348 /// </summary>
262 // ----------------------------------------------------------------- 349 // -----------------------------------------------------------------
263 protected UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name) 350 [ScriptInvocation]
351 public UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name)
264 { 352 {
265 UUID reqID = UUID.Random(); 353 UUID reqID = UUID.Random();
266 Util.FireAndForget(delegate(object o) { DoJsonWriteNotecard(reqID,hostID,scriptID,storeID,path,name); }); 354 Util.FireAndForget(
355 o => DoJsonWriteNotecard(reqID,hostID,scriptID,storeID,path,name), null, "JsonStoreScriptModule.DoJsonWriteNotecard");
267 return reqID; 356 return reqID;
268 } 357 }
269 358
@@ -272,14 +361,41 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
272 /// 361 ///
273 /// </summary> 362 /// </summary>
274 // ----------------------------------------------------------------- 363 // -----------------------------------------------------------------
275 protected int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path) 364 [ScriptInvocation]
365 public string JsonList2Path(UUID hostID, UUID scriptID, object[] pathlist)
366 {
367 string ipath = ConvertList2Path(pathlist);
368 string opath;
369
370 if (JsonStore.CanonicalPathExpression(ipath,out opath))
371 return opath;
372
373 // This won't parse if passed to the other routines as opposed to
374 // returning an empty string which is a valid path and would overwrite
375 // the entire store
376 return "**INVALID**";
377 }
378
379 // -----------------------------------------------------------------
380 /// <summary>
381 ///
382 /// </summary>
383 // -----------------------------------------------------------------
384 [ScriptInvocation]
385 public int JsonGetNodeType(UUID hostID, UUID scriptID, UUID storeID, string path)
276 { 386 {
277 return m_store.TestPath(storeID,path,false) ? 1 : 0; 387 return (int)m_store.GetNodeType(storeID,path);
278 } 388 }
279 389
280 protected int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path) 390 // -----------------------------------------------------------------
391 /// <summary>
392 ///
393 /// </summary>
394 // -----------------------------------------------------------------
395 [ScriptInvocation]
396 public int JsonGetValueType(UUID hostID, UUID scriptID, UUID storeID, string path)
281 { 397 {
282 return m_store.TestPath(storeID,path,true) ? 1 : 0; 398 return (int)m_store.GetValueType(storeID,path);
283 } 399 }
284 400
285 // ----------------------------------------------------------------- 401 // -----------------------------------------------------------------
@@ -287,12 +403,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
287 /// 403 ///
288 /// </summary> 404 /// </summary>
289 // ----------------------------------------------------------------- 405 // -----------------------------------------------------------------
290 protected int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value) 406 [ScriptInvocation]
407 public int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
291 { 408 {
292 return m_store.SetValue(storeID,path,value,false) ? 1 : 0; 409 return m_store.SetValue(storeID,path,value,false) ? 1 : 0;
293 } 410 }
294 411
295 protected int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value) 412 [ScriptInvocation]
413 public int JsonSetJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
296 { 414 {
297 return m_store.SetValue(storeID,path,value,true) ? 1 : 0; 415 return m_store.SetValue(storeID,path,value,true) ? 1 : 0;
298 } 416 }
@@ -302,7 +420,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
302 /// 420 ///
303 /// </summary> 421 /// </summary>
304 // ----------------------------------------------------------------- 422 // -----------------------------------------------------------------
305 protected int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path) 423 [ScriptInvocation]
424 public int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path)
306 { 425 {
307 return m_store.RemoveValue(storeID,path) ? 1 : 0; 426 return m_store.RemoveValue(storeID,path) ? 1 : 0;
308 } 427 }
@@ -312,14 +431,27 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
312 /// 431 ///
313 /// </summary> 432 /// </summary>
314 // ----------------------------------------------------------------- 433 // -----------------------------------------------------------------
315 protected string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path) 434 [ScriptInvocation]
435 public int JsonGetArrayLength(UUID hostID, UUID scriptID, UUID storeID, string path)
436 {
437 return m_store.GetArrayLength(storeID,path);
438 }
439
440 // -----------------------------------------------------------------
441 /// <summary>
442 ///
443 /// </summary>
444 // -----------------------------------------------------------------
445 [ScriptInvocation]
446 public string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path)
316 { 447 {
317 string value = String.Empty; 448 string value = String.Empty;
318 m_store.GetValue(storeID,path,false,out value); 449 m_store.GetValue(storeID,path,false,out value);
319 return value; 450 return value;
320 } 451 }
321 452
322 protected string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) 453 [ScriptInvocation]
454 public string JsonGetJson(UUID hostID, UUID scriptID, UUID storeID, string path)
323 { 455 {
324 string value = String.Empty; 456 string value = String.Empty;
325 m_store.GetValue(storeID,path,true, out value); 457 m_store.GetValue(storeID,path,true, out value);
@@ -331,80 +463,109 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
331 /// 463 ///
332 /// </summary> 464 /// </summary>
333 // ----------------------------------------------------------------- 465 // -----------------------------------------------------------------
334 protected UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path) 466 [ScriptInvocation]
467 public UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path)
335 { 468 {
336 UUID reqID = UUID.Random(); 469 UUID reqID = UUID.Random();
337 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,false); }); 470 Util.FireAndForget(
471 o => DoJsonTakeValue(scriptID,reqID,storeID,path,false), null, "JsonStoreScriptModule.DoJsonTakeValue");
338 return reqID; 472 return reqID;
339 } 473 }
340 474
341 protected UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) 475 [ScriptInvocation]
476 public UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
342 { 477 {
343 UUID reqID = UUID.Random(); 478 UUID reqID = UUID.Random();
344 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,true); }); 479 Util.FireAndForget(
480 o => DoJsonTakeValue(scriptID,reqID,storeID,path,true), null, "JsonStoreScriptModule.DoJsonTakeValueJson");
345 return reqID; 481 return reqID;
346 } 482 }
347 483
348 private void DoJsonTakeValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
349 {
350 try
351 {
352 m_store.TakeValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
353 return;
354 }
355 catch (Exception e)
356 {
357 m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString());
358 }
359
360 DispatchValue(scriptID,reqID,String.Empty);
361 }
362
363
364 // ----------------------------------------------------------------- 484 // -----------------------------------------------------------------
365 /// <summary> 485 /// <summary>
366 /// 486 ///
367 /// </summary> 487 /// </summary>
368 // ----------------------------------------------------------------- 488 // -----------------------------------------------------------------
369 protected UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path) 489 [ScriptInvocation]
490 public UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path)
370 { 491 {
371 UUID reqID = UUID.Random(); 492 UUID reqID = UUID.Random();
372 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,false); }); 493 Util.FireAndForget(
494 o => DoJsonReadValue(scriptID,reqID,storeID,path,false), null, "JsonStoreScriptModule.DoJsonReadValue");
373 return reqID; 495 return reqID;
374 } 496 }
375 497
376 protected UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) 498 [ScriptInvocation]
499 public UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
377 { 500 {
378 UUID reqID = UUID.Random(); 501 UUID reqID = UUID.Random();
379 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,true); }); 502 Util.FireAndForget(
503 o => DoJsonReadValue(scriptID,reqID,storeID,path,true), null, "JsonStoreScriptModule.DoJsonReadValueJson");
380 return reqID; 504 return reqID;
381 } 505 }
382 506
383 private void DoJsonReadValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson) 507#endregion
508
509 // -----------------------------------------------------------------
510 /// <summary>
511 ///
512 /// </summary>
513 // -----------------------------------------------------------------
514 protected void GenerateRuntimeError(string msg)
515 {
516 m_log.InfoFormat("[JsonStore] runtime error: {0}",msg);
517 throw new Exception("JsonStore Runtime Error: " + msg);
518 }
519
520 // -----------------------------------------------------------------
521 /// <summary>
522 ///
523 /// </summary>
524 // -----------------------------------------------------------------
525 protected void DispatchValue(UUID scriptID, UUID reqID, string value)
526 {
527 m_comms.DispatchReply(scriptID,1,value,reqID.ToString());
528 }
529
530 // -----------------------------------------------------------------
531 /// <summary>
532 ///
533 /// </summary>
534 // -----------------------------------------------------------------
535 private void DoJsonTakeValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
384 { 536 {
385 try 537 try
386 { 538 {
387 m_store.ReadValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); }); 539 m_store.TakeValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
388 return; 540 return;
389 } 541 }
390 catch (Exception e) 542 catch (Exception e)
391 { 543 {
392 m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString()); 544 m_log.InfoFormat("[JsonStoreScripts]: unable to retrieve value; {0}",e.ToString());
393 } 545 }
394 546
395 DispatchValue(scriptID,reqID,String.Empty); 547 DispatchValue(scriptID,reqID,String.Empty);
396 } 548 }
397 549
398#endregion
399 550
400 // ----------------------------------------------------------------- 551 // -----------------------------------------------------------------
401 /// <summary> 552 /// <summary>
402 /// 553 ///
403 /// </summary> 554 /// </summary>
404 // ----------------------------------------------------------------- 555 // -----------------------------------------------------------------
405 protected void DispatchValue(UUID scriptID, UUID reqID, string value) 556 private void DoJsonReadValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
406 { 557 {
407 m_comms.DispatchReply(scriptID,1,value,reqID.ToString()); 558 try
559 {
560 m_store.ReadValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
561 return;
562 }
563 catch (Exception e)
564 {
565 m_log.InfoFormat("[JsonStoreScripts]: unable to retrieve value; {0}",e.ToString());
566 }
567
568 DispatchValue(scriptID,reqID,String.Empty);
408 } 569 }
409 570
410 // ----------------------------------------------------------------- 571 // -----------------------------------------------------------------
@@ -412,31 +573,44 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
412 /// 573 ///
413 /// </summary> 574 /// </summary>
414 // ----------------------------------------------------------------- 575 // -----------------------------------------------------------------
415 private void DoJsonReadNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID) 576 private void DoJsonReadNotecard(
577 UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, string notecardIdentifier)
416 { 578 {
579 UUID assetID;
580
581 if (!UUID.TryParse(notecardIdentifier, out assetID))
582 {
583 SceneObjectPart part = m_scene.GetSceneObjectPart(hostID);
584 assetID = ScriptUtils.GetAssetIdFromItemName(part, notecardIdentifier, (int)AssetType.Notecard);
585 }
586
417 AssetBase a = m_scene.AssetService.Get(assetID.ToString()); 587 AssetBase a = m_scene.AssetService.Get(assetID.ToString());
418 if (a == null) 588 if (a == null)
419 GenerateRuntimeError(String.Format("Unable to find notecard asset {0}",assetID)); 589 GenerateRuntimeError(String.Format("Unable to find notecard asset {0}", assetID));
420 590
421 if (a.Type != (sbyte)AssetType.Notecard) 591 if (a.Type != (sbyte)AssetType.Notecard)
422 GenerateRuntimeError(String.Format("Invalid notecard asset {0}",assetID)); 592 GenerateRuntimeError(String.Format("Invalid notecard asset {0}", assetID));
423 593
424 m_log.DebugFormat("[JsonStoreScripts] read notecard in context {0}",storeID); 594 m_log.DebugFormat("[JsonStoreScripts]: read notecard in context {0}",storeID);
425 595
426 try 596 try
427 { 597 {
428 string jsondata = SLUtil.ParseNotecardToString(Encoding.UTF8.GetString(a.Data)); 598 string jsondata = SLUtil.ParseNotecardToString(a.Data);
429 int result = m_store.SetValue(storeID, path, jsondata,true) ? 1 : 0; 599 int result = m_store.SetValue(storeID, path, jsondata,true) ? 1 : 0;
430 m_comms.DispatchReply(scriptID,result, "", reqID.ToString()); 600 m_comms.DispatchReply(scriptID, result, "", reqID.ToString());
431 return; 601 return;
432 } 602 }
603 catch(SLUtil.NotANotecardFormatException e)
604 {
605 m_log.WarnFormat("[JsonStoreScripts]: Notecard parsing failed; assetId {0} at line number {1}", assetID.ToString(), e.lineNumber);
606 }
433 catch (Exception e) 607 catch (Exception e)
434 { 608 {
435 m_log.WarnFormat("[JsonStoreScripts] Json parsing failed; {0}",e.Message); 609 m_log.WarnFormat("[JsonStoreScripts]: Json parsing failed; {0}", e.Message);
436 } 610 }
437 611
438 GenerateRuntimeError(String.Format("Json parsing failed for {0}",assetID.ToString())); 612 GenerateRuntimeError(String.Format("Json parsing failed for {0}", assetID));
439 m_comms.DispatchReply(scriptID,0,"",reqID.ToString()); 613 m_comms.DispatchReply(scriptID, 0, "", reqID.ToString());
440 } 614 }
441 615
442 // ----------------------------------------------------------------- 616 // -----------------------------------------------------------------
@@ -494,5 +668,141 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
494 668
495 m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString()); 669 m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString());
496 } 670 }
671
672 // -----------------------------------------------------------------
673 /// <summary>
674 /// Convert a list of values that are path components to a single string path
675 /// </summary>
676 // -----------------------------------------------------------------
677 protected static Regex m_ArrayPattern = new Regex("^([0-9]+|\\+)$");
678 private string ConvertList2Path(object[] pathlist)
679 {
680 string path = "";
681 for (int i = 0; i < pathlist.Length; i++)
682 {
683 string token = "";
684
685 if (pathlist[i] is string)
686 {
687 token = pathlist[i].ToString();
688
689 // Check to see if this is a bare number which would not be a valid
690 // identifier otherwise
691 if (m_ArrayPattern.IsMatch(token))
692 token = '[' + token + ']';
693 }
694 else if (pathlist[i] is int)
695 {
696 token = "[" + pathlist[i].ToString() + "]";
697 }
698 else
699 {
700 token = "." + pathlist[i].ToString() + ".";
701 }
702
703 path += token + ".";
704 }
705
706 return path;
707 }
708
709 // -----------------------------------------------------------------
710 /// <summary>
711 ///
712 /// </summary>
713 // -----------------------------------------------------------------
714 private void DoJsonRezObject(UUID hostID, UUID scriptID, UUID reqID, string name, Vector3 pos, Vector3 vel, Quaternion rot, string param)
715 {
716 if (Double.IsNaN(rot.X) || Double.IsNaN(rot.Y) || Double.IsNaN(rot.Z) || Double.IsNaN(rot.W))
717 {
718 GenerateRuntimeError("Invalid rez rotation");
719 return;
720 }
721
722 SceneObjectGroup host = m_scene.GetSceneObjectGroup(hostID);
723 if (host == null)
724 {
725 GenerateRuntimeError(String.Format("Unable to find rezzing host '{0}'",hostID));
726 return;
727 }
728
729 // hpos = host.RootPart.GetWorldPosition()
730 // float dist = (float)llVecDist(hpos, pos);
731 // if (dist > m_ScriptDistanceFactor * 10.0f)
732 // return;
733
734 TaskInventoryItem item = host.RootPart.Inventory.GetInventoryItem(name);
735 if (item == null)
736 {
737 GenerateRuntimeError(String.Format("Unable to find object to rez '{0}'",name));
738 return;
739 }
740
741 if (item.InvType != (int)InventoryType.Object)
742 {
743 GenerateRuntimeError("Can't create requested object; object is missing from database");
744 return;
745 }
746
747 List<SceneObjectGroup> objlist;
748 List<Vector3> veclist;
749
750 bool success = host.RootPart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
751 if (! success)
752 {
753 GenerateRuntimeError("Failed to create object");
754 return;
755 }
756
757 int totalPrims = 0;
758 foreach (SceneObjectGroup group in objlist)
759 totalPrims += group.PrimCount;
760
761 if (! m_scene.Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
762 {
763 GenerateRuntimeError("Not allowed to create the object");
764 return;
765 }
766
767 if (! m_scene.Permissions.BypassPermissions())
768 {
769 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
770 host.RootPart.Inventory.RemoveInventoryItem(item.ItemID);
771 }
772
773 for (int i = 0; i < objlist.Count; i++)
774 {
775 SceneObjectGroup group = objlist[i];
776 Vector3 curpos = pos + veclist[i];
777
778 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
779 {
780 group.RootPart.AttachedPos = group.AbsolutePosition;
781 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
782 }
783
784 group.FromPartID = host.RootPart.UUID;
785 m_scene.AddNewSceneObject(group, true, curpos, rot, vel);
786
787 UUID storeID = group.UUID;
788 if (! m_store.CreateStore(param, ref storeID))
789 {
790 GenerateRuntimeError("Unable to create jsonstore for new object");
791 continue;
792 }
793
794 // We can only call this after adding the scene object, since the scene object references the scene
795 // to find out if scripts should be activated at all.
796 group.RootPart.SetDieAtEdge(true);
797 group.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 3);
798 group.ResumeScripts();
799
800 group.ScheduleGroupForFullUpdate();
801
802 // send the reply back to the host object, use the integer param to indicate the number
803 // of remaining objects
804 m_comms.DispatchReply(scriptID, objlist.Count-i-1, group.RootPart.UUID.ToString(), reqID.ToString());
805 }
806 }
497 } 807 }
498} 808}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
new file mode 100644
index 0000000..99a7076
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
@@ -0,0 +1,900 @@
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.Reflection;
31using System.Text;
32using log4net;
33using Nini.Config;
34using NUnit.Framework;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.Scripting.ScriptModuleComms;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.ScriptEngine.Shared;
40using OpenSim.Region.ScriptEngine.Shared.Api;
41using OpenSim.Services.Interfaces;
42using OpenSim.Tests.Common;
43
44namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
45{
46 /// <summary>
47 /// Tests for inventory functions in LSL
48 /// </summary>
49 [TestFixture]
50 public class JsonStoreScriptModuleTests : OpenSimTestCase
51 {
52 private Scene m_scene;
53 private MockScriptEngine m_engine;
54 private ScriptModuleCommsModule m_smcm;
55 private JsonStoreScriptModule m_jssm;
56
57 [TestFixtureSetUp]
58 public void FixtureInit()
59 {
60 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
61 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
62 }
63
64 [TestFixtureTearDown]
65 public void TearDown()
66 {
67 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
68 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
69 // tests really shouldn't).
70 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
71 }
72
73 [SetUp]
74 public override void SetUp()
75 {
76 base.SetUp();
77
78 IConfigSource configSource = new IniConfigSource();
79 IConfig jsonStoreConfig = configSource.AddConfig("JsonStore");
80 jsonStoreConfig.Set("Enabled", "true");
81
82 m_engine = new MockScriptEngine();
83 m_smcm = new ScriptModuleCommsModule();
84 JsonStoreModule jsm = new JsonStoreModule();
85 m_jssm = new JsonStoreScriptModule();
86
87 m_scene = new SceneHelpers().SetupScene();
88 SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, m_jssm);
89
90 try
91 {
92 m_smcm.RegisterScriptInvocation(this, "DummyTestMethod");
93 }
94 catch (ArgumentException)
95 {
96 Assert.Ignore("Ignoring test since running on .NET 3.5 or earlier.");
97 }
98
99 // XXX: Unfortunately, ICommsModule currently has no way of deregistering methods.
100 }
101
102 private object InvokeOp(string name, params object[] args)
103 {
104 return InvokeOpOnHost(name, UUID.Zero, args);
105 }
106
107 private object InvokeOpOnHost(string name, UUID hostId, params object[] args)
108 {
109 return m_smcm.InvokeOperation(hostId, UUID.Zero, name, args);
110 }
111
112 [Test]
113 public void TestJsonCreateStore()
114 {
115 TestHelpers.InMethod();
116// TestHelpers.EnableLogging();
117
118 // Test blank store
119 {
120 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
121 Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
122 }
123
124 // Test single element store
125 {
126 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
127 Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
128 }
129
130 // Test with an integer value
131 {
132 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 42.15 }");
133 Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
134
135 string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
136 Assert.That(value, Is.EqualTo("42.15"));
137 }
138
139 // Test with an array as the root node
140 {
141 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "[ 'one', 'two', 'three' ]");
142 Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
143
144 string value = (string)InvokeOp("JsonGetValue", storeId, "[1]");
145 Assert.That(value, Is.EqualTo("two"));
146 }
147 }
148
149 [Test]
150 public void TestJsonDestroyStore()
151 {
152 TestHelpers.InMethod();
153// TestHelpers.EnableLogging();
154
155 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
156 int dsrv = (int)InvokeOp("JsonDestroyStore", storeId);
157
158 Assert.That(dsrv, Is.EqualTo(1));
159
160 int tprv = (int)InvokeOp("JsonGetNodeType", storeId, "Hello");
161 Assert.That(tprv, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF));
162 }
163
164 [Test]
165 public void TestJsonDestroyStoreNotExists()
166 {
167 TestHelpers.InMethod();
168// TestHelpers.EnableLogging();
169
170 UUID fakeStoreId = TestHelpers.ParseTail(0x500);
171
172 int dsrv = (int)InvokeOp("JsonDestroyStore", fakeStoreId);
173
174 Assert.That(dsrv, Is.EqualTo(0));
175 }
176
177 [Test]
178 public void TestJsonGetValue()
179 {
180 TestHelpers.InMethod();
181// TestHelpers.EnableLogging();
182
183 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }");
184
185 {
186 string value = (string)InvokeOp("JsonGetValue", storeId, "Hello.World");
187 Assert.That(value, Is.EqualTo("Two"));
188 }
189
190 // Test get of path section instead of leaf
191 {
192 string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
193 Assert.That(value, Is.EqualTo(""));
194 }
195
196 // Test get of non-existing value
197 {
198 string fakeValueGet = (string)InvokeOp("JsonGetValue", storeId, "foo");
199 Assert.That(fakeValueGet, Is.EqualTo(""));
200 }
201
202 // Test get from non-existing store
203 {
204 UUID fakeStoreId = TestHelpers.ParseTail(0x500);
205 string fakeStoreValueGet = (string)InvokeOp("JsonGetValue", fakeStoreId, "Hello");
206 Assert.That(fakeStoreValueGet, Is.EqualTo(""));
207 }
208 }
209
210 [Test]
211 public void TestJsonGetJson()
212 {
213 TestHelpers.InMethod();
214// TestHelpers.EnableLogging();
215
216 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }");
217
218 {
219 string value = (string)InvokeOp("JsonGetJson", storeId, "Hello.World");
220 Assert.That(value, Is.EqualTo("'Two'"));
221 }
222
223 // Test get of path section instead of leaf
224 {
225 string value = (string)InvokeOp("JsonGetJson", storeId, "Hello");
226 Assert.That(value, Is.EqualTo("{\"World\":\"Two\"}"));
227 }
228
229 // Test get of non-existing value
230 {
231 string fakeValueGet = (string)InvokeOp("JsonGetJson", storeId, "foo");
232 Assert.That(fakeValueGet, Is.EqualTo(""));
233 }
234
235 // Test get from non-existing store
236 {
237 UUID fakeStoreId = TestHelpers.ParseTail(0x500);
238 string fakeStoreValueGet = (string)InvokeOp("JsonGetJson", fakeStoreId, "Hello");
239 Assert.That(fakeStoreValueGet, Is.EqualTo(""));
240 }
241 }
242
243// [Test]
244// public void TestJsonTakeValue()
245// {
246// TestHelpers.InMethod();
247//// TestHelpers.EnableLogging();
248//
249// UUID storeId
250// = (UUID)m_smcm.InvokeOperation(
251// UUID.Zero, UUID.Zero, "JsonCreateStore", new object[] { "{ 'Hello' : 'World' }" });
252//
253// string value
254// = (string)m_smcm.InvokeOperation(
255// UUID.Zero, UUID.Zero, "JsonTakeValue", new object[] { storeId, "Hello" });
256//
257// Assert.That(value, Is.EqualTo("World"));
258//
259// string value2
260// = (string)m_smcm.InvokeOperation(
261// UUID.Zero, UUID.Zero, "JsonGetValue", new object[] { storeId, "Hello" });
262//
263// Assert.That(value, Is.Null);
264// }
265
266 [Test]
267 public void TestJsonRemoveValue()
268 {
269 TestHelpers.InMethod();
270// TestHelpers.EnableLogging();
271
272 // Test remove of node in object pointing to a string
273 {
274 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
275
276 int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
277 Assert.That(returnValue, Is.EqualTo(1));
278
279 int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello");
280 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF));
281
282 string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
283 Assert.That(returnValue2, Is.EqualTo(""));
284 }
285
286 // Test remove of node in object pointing to another object
287 {
288 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Wally' } }");
289
290 int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
291 Assert.That(returnValue, Is.EqualTo(1));
292
293 int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello");
294 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF));
295
296 string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello");
297 Assert.That(returnValue2, Is.EqualTo(""));
298 }
299
300 // Test remove of node in an array
301 {
302 UUID storeId
303 = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : [ 'value1', 'value2' ] }");
304
305 int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]");
306 Assert.That(returnValue, Is.EqualTo(1));
307
308 int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello[0]");
309 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE));
310
311 result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello[1]");
312 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF));
313
314 string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]");
315 Assert.That(stringReturnValue, Is.EqualTo("value2"));
316
317 stringReturnValue = (string)InvokeOp("JsonGetJson", storeId, "Hello[1]");
318 Assert.That(stringReturnValue, Is.EqualTo(""));
319 }
320
321 // Test remove of non-existing value
322 {
323 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
324
325 int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Cheese");
326 Assert.That(fakeValueRemove, Is.EqualTo(0));
327 }
328
329 {
330 // Test get from non-existing store
331 UUID fakeStoreId = TestHelpers.ParseTail(0x500);
332 int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello");
333 Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
334 }
335 }
336
337// [Test]
338// public void TestJsonTestPath()
339// {
340// TestHelpers.InMethod();
341//// TestHelpers.EnableLogging();
342//
343// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }");
344//
345// {
346// int result = (int)InvokeOp("JsonTestPath", storeId, "Hello.World");
347// Assert.That(result, Is.EqualTo(1));
348// }
349//
350// // Test for path which does not resolve to a value.
351// {
352// int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
353// Assert.That(result, Is.EqualTo(0));
354// }
355//
356// {
357// int result2 = (int)InvokeOp("JsonTestPath", storeId, "foo");
358// Assert.That(result2, Is.EqualTo(0));
359// }
360//
361// // Test with fake store
362// {
363// UUID fakeStoreId = TestHelpers.ParseTail(0x500);
364// int fakeStoreValueRemove = (int)InvokeOp("JsonTestPath", fakeStoreId, "Hello");
365// Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
366// }
367// }
368
369// [Test]
370// public void TestJsonTestPathJson()
371// {
372// TestHelpers.InMethod();
373//// TestHelpers.EnableLogging();
374//
375// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }");
376//
377// {
378// int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello.World");
379// Assert.That(result, Is.EqualTo(1));
380// }
381//
382// // Test for path which does not resolve to a value.
383// {
384// int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello");
385// Assert.That(result, Is.EqualTo(1));
386// }
387//
388// {
389// int result2 = (int)InvokeOp("JsonTestPathJson", storeId, "foo");
390// Assert.That(result2, Is.EqualTo(0));
391// }
392//
393// // Test with fake store
394// {
395// UUID fakeStoreId = TestHelpers.ParseTail(0x500);
396// int fakeStoreValueRemove = (int)InvokeOp("JsonTestPathJson", fakeStoreId, "Hello");
397// Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
398// }
399// }
400
401 [Test]
402 public void TestJsonGetArrayLength()
403 {
404 TestHelpers.InMethod();
405// TestHelpers.EnableLogging();
406
407 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }");
408
409 {
410 int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello.World");
411 Assert.That(result, Is.EqualTo(2));
412 }
413
414 // Test path which is not an array
415 {
416 int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello");
417 Assert.That(result, Is.EqualTo(-1));
418 }
419
420 // Test fake path
421 {
422 int result = (int)InvokeOp("JsonGetArrayLength", storeId, "foo");
423 Assert.That(result, Is.EqualTo(-1));
424 }
425
426 // Test fake store
427 {
428 UUID fakeStoreId = TestHelpers.ParseTail(0x500);
429 int result = (int)InvokeOp("JsonGetArrayLength", fakeStoreId, "Hello.World");
430 Assert.That(result, Is.EqualTo(-1));
431 }
432 }
433
434 [Test]
435 public void TestJsonGetNodeType()
436 {
437 TestHelpers.InMethod();
438// TestHelpers.EnableLogging();
439
440 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }");
441
442 {
443 int result = (int)InvokeOp("JsonGetNodeType", storeId, ".");
444 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_OBJECT));
445 }
446
447 {
448 int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello");
449 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_OBJECT));
450 }
451
452 {
453 int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World");
454 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_ARRAY));
455 }
456
457 {
458 int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World[0]");
459 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE));
460 }
461
462 {
463 int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World[1]");
464 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE));
465 }
466
467 // Test for non-existent path
468 {
469 int result = (int)InvokeOp("JsonGetNodeType", storeId, "foo");
470 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF));
471 }
472
473 // Test for non-existent store
474 {
475 UUID fakeStoreId = TestHelpers.ParseTail(0x500);
476 int result = (int)InvokeOp("JsonGetNodeType", fakeStoreId, ".");
477 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF));
478 }
479 }
480
481 [Test]
482 public void TestJsonList2Path()
483 {
484 TestHelpers.InMethod();
485// TestHelpers.EnableLogging();
486
487 // Invoking these methods directly since I just couldn't get comms module invocation to work for some reason
488 // - some confusion with the methods that take a params object[] invocation.
489 {
490 string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo" });
491 Assert.That(result, Is.EqualTo("{foo}"));
492 }
493
494 {
495 string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", "bar" });
496 Assert.That(result, Is.EqualTo("{foo}.{bar}"));
497 }
498
499 {
500 string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", 1, "bar" });
501 Assert.That(result, Is.EqualTo("{foo}.[1].{bar}"));
502 }
503 }
504
505 [Test]
506 public void TestJsonSetValue()
507 {
508 TestHelpers.InMethod();
509// TestHelpers.EnableLogging();
510
511 {
512 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
513
514 int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times");
515 Assert.That(result, Is.EqualTo(1));
516
517 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
518 Assert.That(value, Is.EqualTo("Times"));
519 }
520
521 // Test setting a key containing periods with delineation
522 {
523 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
524
525 int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun.Circus}", "Times");
526 Assert.That(result, Is.EqualTo(1));
527
528 string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun.Circus}");
529 Assert.That(value, Is.EqualTo("Times"));
530 }
531
532 // *** Test [] ***
533
534 // Test setting a key containing unbalanced ] without delineation. Expecting failure
535 {
536 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
537
538 int result = (int)InvokeOp("JsonSetValue", storeId, "Fun]Circus", "Times");
539 Assert.That(result, Is.EqualTo(0));
540
541 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun]Circus");
542 Assert.That(value, Is.EqualTo(""));
543 }
544
545 // Test setting a key containing unbalanced [ without delineation. Expecting failure
546 {
547 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
548
549 int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[Circus", "Times");
550 Assert.That(result, Is.EqualTo(0));
551
552 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[Circus");
553 Assert.That(value, Is.EqualTo(""));
554 }
555
556 // Test setting a key containing unbalanced [] without delineation. Expecting failure
557 {
558 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
559
560 int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[]Circus", "Times");
561 Assert.That(result, Is.EqualTo(0));
562
563 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[]Circus");
564 Assert.That(value, Is.EqualTo(""));
565 }
566
567 // Test setting a key containing unbalanced ] with delineation
568 {
569 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
570
571 int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun]Circus}", "Times");
572 Assert.That(result, Is.EqualTo(1));
573
574 string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun]Circus}");
575 Assert.That(value, Is.EqualTo("Times"));
576 }
577
578 // Test setting a key containing unbalanced [ with delineation
579 {
580 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
581
582 int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[Circus}", "Times");
583 Assert.That(result, Is.EqualTo(1));
584
585 string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[Circus}");
586 Assert.That(value, Is.EqualTo("Times"));
587 }
588
589 // Test setting a key containing empty balanced [] with delineation
590 {
591 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
592
593 int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[]Circus}", "Times");
594 Assert.That(result, Is.EqualTo(1));
595
596 string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[]Circus}");
597 Assert.That(value, Is.EqualTo("Times"));
598 }
599
600// // Commented out as this currently unexpectedly fails.
601// // Test setting a key containing brackets around an integer with delineation
602// {
603// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
604//
605// int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[0]Circus}", "Times");
606// Assert.That(result, Is.EqualTo(1));
607//
608// string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[0]Circus}");
609// Assert.That(value, Is.EqualTo("Times"));
610// }
611
612 // *** Test {} ***
613
614 // Test setting a key containing unbalanced } without delineation. Expecting failure (?)
615 {
616 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
617
618 int result = (int)InvokeOp("JsonSetValue", storeId, "Fun}Circus", "Times");
619 Assert.That(result, Is.EqualTo(0));
620
621 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus");
622 Assert.That(value, Is.EqualTo(""));
623 }
624
625 // Test setting a key containing unbalanced { without delineation. Expecting failure (?)
626 {
627 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
628
629 int result = (int)InvokeOp("JsonSetValue", storeId, "Fun{Circus", "Times");
630 Assert.That(result, Is.EqualTo(0));
631
632 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus");
633 Assert.That(value, Is.EqualTo(""));
634 }
635
636// // Commented out as this currently unexpectedly fails.
637// // Test setting a key containing unbalanced }
638// {
639// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
640//
641// int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun}Circus}", "Times");
642// Assert.That(result, Is.EqualTo(0));
643// }
644
645 // Test setting a key containing unbalanced { with delineation
646 {
647 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
648
649 int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Circus}", "Times");
650 Assert.That(result, Is.EqualTo(1));
651
652 string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Circus}");
653 Assert.That(value, Is.EqualTo("Times"));
654 }
655
656 // Test setting a key containing balanced {} with delineation. This should fail.
657 {
658 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
659
660 int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Filled}Circus}", "Times");
661 Assert.That(result, Is.EqualTo(0));
662
663 string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Filled}Circus}");
664 Assert.That(value, Is.EqualTo(""));
665 }
666
667 // Test setting to location that does not exist. This should fail.
668 {
669 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
670
671 int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times");
672 Assert.That(result, Is.EqualTo(0));
673
674 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus");
675 Assert.That(value, Is.EqualTo(""));
676 }
677
678 // Test with fake store
679 {
680 UUID fakeStoreId = TestHelpers.ParseTail(0x500);
681 int fakeStoreValueSet = (int)InvokeOp("JsonSetValue", fakeStoreId, "Hello", "World");
682 Assert.That(fakeStoreValueSet, Is.EqualTo(0));
683 }
684 }
685
686 [Test]
687 public void TestJsonSetJson()
688 {
689 TestHelpers.InMethod();
690// TestHelpers.EnableLogging();
691
692 // Single quoted token case
693 {
694 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
695
696 int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "'Times'");
697 Assert.That(result, Is.EqualTo(1));
698
699 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
700 Assert.That(value, Is.EqualTo("Times"));
701 }
702
703 // Sub-tree case
704 {
705 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
706
707 int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "{ 'Filled' : 'Times' }");
708 Assert.That(result, Is.EqualTo(1));
709
710 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Filled");
711 Assert.That(value, Is.EqualTo("Times"));
712 }
713
714 // If setting single strings in JsonSetValueJson, these must be single quoted tokens, not bare strings.
715 {
716 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
717
718 int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "Times");
719 Assert.That(result, Is.EqualTo(0));
720
721 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
722 Assert.That(value, Is.EqualTo(""));
723 }
724
725 // Test setting to location that does not exist. This should fail.
726 {
727 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
728
729 int result = (int)InvokeOp("JsonSetJson", storeId, "Fun.Circus", "'Times'");
730 Assert.That(result, Is.EqualTo(0));
731
732 string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus");
733 Assert.That(value, Is.EqualTo(""));
734 }
735
736 // Test with fake store
737 {
738 UUID fakeStoreId = TestHelpers.ParseTail(0x500);
739 int fakeStoreValueSet = (int)InvokeOp("JsonSetJson", fakeStoreId, "Hello", "'World'");
740 Assert.That(fakeStoreValueSet, Is.EqualTo(0));
741 }
742 }
743
744 /// <summary>
745 /// Test for writing json to a notecard
746 /// </summary>
747 /// <remarks>
748 /// TODO: Really needs to test correct receipt of the link_message event. Could do this by directly fetching
749 /// it via the MockScriptEngine or perhaps by a dummy script instance.
750 /// </remarks>
751 [Test]
752 public void TestJsonWriteNotecard()
753 {
754 TestHelpers.InMethod();
755// TestHelpers.EnableLogging();
756
757 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1));
758 m_scene.AddSceneObject(so);
759
760 UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello':'World' }");
761
762 {
763 string notecardName = "nc1";
764
765 // Write notecard
766 UUID writeNotecardRequestId = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, storeId, "", notecardName);
767 Assert.That(writeNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
768
769 TaskInventoryItem nc1Item = so.RootPart.Inventory.GetInventoryItem(notecardName);
770 Assert.That(nc1Item, Is.Not.Null);
771
772 // TODO: Should independently check the contents.
773 }
774
775 // TODO: Write partial test
776
777 {
778 // Try to write notecard for a bad path
779 // In this case we do get a request id but no notecard is written.
780 string badPathNotecardName = "badPathNotecardName";
781
782 UUID writeNotecardBadPathRequestId
783 = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, storeId, "flibble", badPathNotecardName);
784 Assert.That(writeNotecardBadPathRequestId, Is.Not.EqualTo(UUID.Zero));
785
786 TaskInventoryItem badPathItem = so.RootPart.Inventory.GetInventoryItem(badPathNotecardName);
787 Assert.That(badPathItem, Is.Null);
788 }
789
790 {
791 // Test with fake store
792 // In this case we do get a request id but no notecard is written.
793 string fakeStoreNotecardName = "fakeStoreNotecardName";
794
795 UUID fakeStoreId = TestHelpers.ParseTail(0x500);
796 UUID fakeStoreWriteNotecardValue
797 = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, fakeStoreId, "", fakeStoreNotecardName);
798 Assert.That(fakeStoreWriteNotecardValue, Is.Not.EqualTo(UUID.Zero));
799
800 TaskInventoryItem fakeStoreItem = so.RootPart.Inventory.GetInventoryItem(fakeStoreNotecardName);
801 Assert.That(fakeStoreItem, Is.Null);
802 }
803 }
804
805 /// <summary>
806 /// Test for reading json from a notecard
807 /// </summary>
808 /// <remarks>
809 /// TODO: Really needs to test correct receipt of the link_message event. Could do this by directly fetching
810 /// it via the MockScriptEngine or perhaps by a dummy script instance.
811 /// </remarks>
812 [Test]
813 public void TestJsonReadNotecard()
814 {
815 TestHelpers.InMethod();
816// TestHelpers.EnableLogging();
817
818 string notecardName = "nc1";
819
820 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1));
821 m_scene.AddSceneObject(so);
822
823 UUID creatingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello':'World' }");
824
825 // Write notecard
826 InvokeOpOnHost("JsonWriteNotecard", so.UUID, creatingStoreId, "", notecardName);
827
828 {
829 // Read notecard
830 UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}");
831 UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "", notecardName);
832 Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
833
834 string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello");
835 Assert.That(value, Is.EqualTo("World"));
836 }
837
838 {
839 // Read notecard to new single component path
840 UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}");
841 UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make", notecardName);
842 Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
843
844 string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello");
845 Assert.That(value, Is.EqualTo(""));
846
847 value = (string)InvokeOp("JsonGetValue", receivingStoreId, "make.Hello");
848 Assert.That(value, Is.EqualTo("World"));
849 }
850
851 {
852 // Read notecard to new multi-component path. This should not work.
853 UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}");
854 UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make.it", notecardName);
855 Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
856
857 string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello");
858 Assert.That(value, Is.EqualTo(""));
859
860 value = (string)InvokeOp("JsonGetValue", receivingStoreId, "make.it.Hello");
861 Assert.That(value, Is.EqualTo(""));
862 }
863
864 {
865 // Read notecard to existing multi-component path. This should work
866 UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'make' : { 'it' : 'so' } }");
867 UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make.it", notecardName);
868 Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
869
870 string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello");
871 Assert.That(value, Is.EqualTo(""));
872
873 value = (string)InvokeOp("JsonGetValue", receivingStoreId, "make.it.Hello");
874 Assert.That(value, Is.EqualTo("World"));
875 }
876
877 {
878 // Read notecard to invalid path. This should not work.
879 UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'make' : { 'it' : 'so' } }");
880 UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "/", notecardName);
881 Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
882
883 string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello");
884 Assert.That(value, Is.EqualTo(""));
885 }
886
887 {
888 // Try read notecard to fake store.
889 UUID fakeStoreId = TestHelpers.ParseTail(0x500);
890 UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, fakeStoreId, "", notecardName);
891 Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
892
893 string value = (string)InvokeOp("JsonGetValue", fakeStoreId, "Hello");
894 Assert.That(value, Is.EqualTo(""));
895 }
896 }
897
898 public object DummyTestMethod(object o1, object o2, object o3, object o4, object o5) { return null; }
899 }
900}
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
index 6fb28e2..4bafe2f 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
@@ -180,6 +180,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
180 /// * Internet 180 /// * Internet
181 /// * Everything 181 /// * Everything
182 /// </remarks> 182 /// </remarks>
183#pragma warning disable 0618
183 public static AppDomain CreateRestrictedDomain(string permissionSetName, string appDomainName) 184 public static AppDomain CreateRestrictedDomain(string permissionSetName, string appDomainName)
184 { 185 {
185 if (permissionSetName == null) 186 if (permissionSetName == null)
@@ -240,6 +241,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
240 241
241 return restrictedDomain; 242 return restrictedDomain;
242 } 243 }
244#pragma warning restore 0618
243 245
244 246
245 void EventManager_OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource) 247 void EventManager_OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource)
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
index 5ed1514..47b9c09 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
@@ -34,7 +34,7 @@ using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.OptionalModules.Scripting.Minimodule.Object; 36using OpenSim.Region.OptionalModules.Scripting.Minimodule.Object;
37using OpenSim.Region.Physics.Manager; 37using OpenSim.Region.PhysicsModules.SharedBase;
38using PrimType=OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.PrimType; 38using PrimType=OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.PrimType;
39using SculptType=OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.SculptType; 39using SculptType=OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.SculptType;
40 40
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index c550c44..870c0bb 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -105,7 +105,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
105 m_scene.LoginLock = true; 105 m_scene.LoginLock = true;
106 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; 106 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
107 107
108 m_log.InfoFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name); 108 // This should always show up to the user but should not trigger warn/errors as these messages are
109 // expected and are not simulator problems. Ideally, there would be a status level in log4net but
110 // failing that, we will print out to console instead.
111 MainConsole.Instance.OutputFormat("Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name);
109 112
110 if (m_uri != string.Empty) 113 if (m_uri != string.Empty)
111 { 114 {
@@ -169,7 +172,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
169 c.Channel = m_channelNotify; 172 c.Channel = m_channelNotify;
170 c.Message += numScriptsFailed.ToString() + "," + message; 173 c.Message += numScriptsFailed.ToString() + "," + message;
171 c.Type = ChatTypeEnum.Region; 174 c.Type = ChatTypeEnum.Region;
172 c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30); 175 if (m_scene != null)
176 c.Position = new Vector3((m_scene.RegionInfo.RegionSizeX * 0.5f), (m_scene.RegionInfo.RegionSizeY * 0.5f), 30);
177 else
178 c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30);
173 c.Sender = null; 179 c.Sender = null;
174 c.SenderUUID = UUID.Zero; 180 c.SenderUUID = UUID.Zero;
175 c.Scene = m_scene; 181 c.Scene = m_scene;
@@ -215,8 +221,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
215 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", 221 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}",
216 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); 222 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString());
217 223
218 m_log.InfoFormat( 224 // Putting this out to console to make it eye-catching for people who are running OpenSimulator
219 "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); 225 // without info log messages enabled. Making this a warning is arguably misleading since it isn't a
226 // warning, and monitor scripts looking for warn/error/fatal messages will received false positives.
227 // Arguably, log4net needs a status log level (like Apache).
228 MainConsole.Instance.OutputFormat("INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name);
220 } 229 }
221 230
222 m_scene.SceneGridService.InformNeighborsThatRegionisUp( 231 m_scene.SceneGridService.InformNeighborsThatRegionisUp(
@@ -297,7 +306,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
297 finally 306 finally
298 { 307 {
299 if (os != null) 308 if (os != null)
300 os.Close(); 309 os.Dispose();
301 } 310 }
302 } 311 }
303 } 312 }
diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
index 709d389..744d1e3 100644
--- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
@@ -35,7 +35,6 @@ using OpenMetaverse;
35using Mono.Addins; 35using Mono.Addins;
36 36
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Communications;
39using OpenSim.Framework.Servers; 38using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer; 39using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Framework.Client; 40using OpenSim.Framework.Client;
diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/OptionalModules/UserStatistics/ActiveConnectionsAJAX.cs
index 3243a9a..6a1112c 100644
--- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/ActiveConnectionsAJAX.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32using System.Text; 32using System.Text;
33using Mono.Data.SqliteClient; 33using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework.Monitoring; 38using OpenSim.Framework.Monitoring;
@@ -51,7 +52,6 @@ namespace OpenSim.Region.UserStatistics
51 52
52 public Hashtable ProcessModel(Hashtable pParams) 53 public Hashtable ProcessModel(Hashtable pParams)
53 { 54 {
54
55 List<Scene> m_scene = (List<Scene>)pParams["Scenes"]; 55 List<Scene> m_scene = (List<Scene>)pParams["Scenes"];
56 56
57 Hashtable nh = new Hashtable(); 57 Hashtable nh = new Hashtable();
@@ -129,6 +129,86 @@ namespace OpenSim.Region.UserStatistics
129 return output.ToString(); 129 return output.ToString();
130 } 130 }
131 131
132 /// <summary>
133 /// Convert active connections information to JSON string. Returns a structure:
134 /// <pre>
135 /// {"regionName": {
136 /// "presenceName": {
137 /// "name": "presenceName",
138 /// "position": "<x,y,z>",
139 /// "isRoot": "false",
140 /// "throttle": {
141 /// },
142 /// "queue": {
143 /// }
144 /// },
145 /// ... // multiple presences in the scene
146 /// },
147 /// ... // multiple regions in the sim
148 /// }
149 ///
150 /// </pre>
151 /// </summary>
152 /// <param name="pModelResult"></param>
153 /// <returns></returns>
154 public string RenderJson(Hashtable pModelResult)
155 {
156 List<Scene> all_scenes = (List<Scene>) pModelResult["hdata"];
157
158 OSDMap regionInfo = new OSDMap();
159 foreach (Scene scene in all_scenes)
160 {
161 OSDMap sceneInfo = new OpenMetaverse.StructuredData.OSDMap();
162 List<ScenePresence> avatarInScene = scene.GetScenePresences();
163 foreach (ScenePresence av in avatarInScene)
164 {
165 OSDMap presenceInfo = new OSDMap();
166 presenceInfo.Add("Name", new OSDString(av.Name));
167
168 Dictionary<string,string> queues = new Dictionary<string, string>();
169 if (av.ControllingClient is IStatsCollector)
170 {
171 IStatsCollector isClient = (IStatsCollector) av.ControllingClient;
172 queues = decodeQueueReport(isClient.Report());
173 }
174 OSDMap queueInfo = new OpenMetaverse.StructuredData.OSDMap();
175 foreach (KeyValuePair<string, string> kvp in queues) {
176 queueInfo.Add(kvp.Key, new OSDString(kvp.Value));
177 }
178 sceneInfo.Add("queues", queueInfo);
179
180 if (av.IsChildAgent)
181 presenceInfo.Add("isRoot", new OSDString("false"));
182 else
183 presenceInfo.Add("isRoot", new OSDString("true"));
184
185 if (av.AbsolutePosition == DefaultNeighborPosition)
186 {
187 presenceInfo.Add("position", new OSDString("<0, 0, 0>"));
188 }
189 else
190 {
191 presenceInfo.Add("position", new OSDString(string.Format("<{0},{1},{2}>",
192 (int)av.AbsolutePosition.X,
193 (int) av.AbsolutePosition.Y,
194 (int) av.AbsolutePosition.Z)) );
195 }
196
197 Dictionary<string, int> throttles = DecodeClientThrottles(av.ControllingClient.GetThrottlesPacked(1));
198 OSDMap throttleInfo = new OpenMetaverse.StructuredData.OSDMap();
199 foreach (string throttlename in throttles.Keys)
200 {
201 throttleInfo.Add(throttlename, new OSDString(throttles[throttlename].ToString()));
202 }
203 presenceInfo.Add("throttle", throttleInfo);
204
205 sceneInfo.Add(av.Name, presenceInfo);
206 }
207 regionInfo.Add(scene.RegionInfo.RegionName, sceneInfo);
208 }
209 return regionInfo.ToString();
210 }
211
132 public Dictionary<string, int> DecodeClientThrottles(byte[] throttle) 212 public Dictionary<string, int> DecodeClientThrottles(byte[] throttle)
133 { 213 {
134 Dictionary<string, int> returndict = new Dictionary<string, int>(); 214 Dictionary<string, int> returndict = new Dictionary<string, int>();
@@ -203,7 +283,7 @@ namespace OpenSim.Region.UserStatistics
203 returndic.Add("Cloud", rep.Substring((7 * pos) , 8)); pos++; 283 returndic.Add("Cloud", rep.Substring((7 * pos) , 8)); pos++;
204 returndic.Add("Task", rep.Substring((7 * pos) , 8)); pos++; 284 returndic.Add("Task", rep.Substring((7 * pos) , 8)); pos++;
205 returndic.Add("Texture", rep.Substring((7 * pos), 8)); pos++; 285 returndic.Add("Texture", rep.Substring((7 * pos), 8)); pos++;
206 returndic.Add("Asset", rep.Substring((7 * pos), 8)); 286 returndic.Add("Asset", rep.Substring((7 * pos), 8));
207 /* 287 /*
208 * return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", 288 * return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
209 SendQueue.Count(), 289 SendQueue.Count(),
diff --git a/OpenSim/Region/UserStatistics/Clients_report.cs b/OpenSim/Region/OptionalModules/UserStatistics/Clients_report.cs
index b2bb33b..4a6f7be 100644
--- a/OpenSim/Region/UserStatistics/Clients_report.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/Clients_report.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Text; 31using System.Text;
32using Mono.Data.SqliteClient; 32using Mono.Data.SqliteClient;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
34using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
35 36
36namespace OpenSim.Region.UserStatistics 37namespace OpenSim.Region.UserStatistics
@@ -44,6 +45,32 @@ namespace OpenSim.Region.UserStatistics
44 get { return "Client"; } 45 get { return "Client"; }
45 } 46 }
46 47
48 /// <summary>
49 /// Return summar information in the form:
50 /// <pre>
51 /// {"totalUsers": "34",
52 /// "totalSessions": "233",
53 /// ...
54 /// }
55 /// </pre>
56 /// </summary>
57 /// <param name="pModelResult"></param>
58 /// <returns></returns>
59 public string RenderJson(Hashtable pModelResult) {
60 stats_default_page_values values = (stats_default_page_values) pModelResult["hdata"];
61
62 OSDMap summaryInfo = new OpenMetaverse.StructuredData.OSDMap();
63 summaryInfo.Add("totalUsers", new OSDString(values.total_num_users.ToString()));
64 summaryInfo.Add("totalSessions", new OSDString(values.total_num_sessions.ToString()));
65 summaryInfo.Add("averageClientFPS", new OSDString(values.avg_client_fps.ToString()));
66 summaryInfo.Add("averageClientMem", new OSDString(values.avg_client_mem_use.ToString()));
67 summaryInfo.Add("averageSimFPS", new OSDString(values.avg_sim_fps.ToString()));
68 summaryInfo.Add("averagePingTime", new OSDString(values.avg_ping.ToString()));
69 summaryInfo.Add("totalKBOut", new OSDString(values.total_kb_out.ToString()));
70 summaryInfo.Add("totalKBIn", new OSDString(values.total_kb_in.ToString()));
71 return summaryInfo.ToString();
72 }
73
47 public Hashtable ProcessModel(Hashtable pParams) 74 public Hashtable ProcessModel(Hashtable pParams)
48 { 75 {
49 SqliteConnection dbConn = (SqliteConnection)pParams["DatabaseConnection"]; 76 SqliteConnection dbConn = (SqliteConnection)pParams["DatabaseConnection"];
diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/OptionalModules/UserStatistics/Default_Report.cs
index cdc615c..fabe3d4 100644
--- a/OpenSim/Region/UserStatistics/Default_Report.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/Default_Report.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32using System.Text; 32using System.Text;
33using Mono.Data.SqliteClient; 33using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
35using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
36using OpenSim.Framework.Monitoring; 37using OpenSim.Framework.Monitoring;
37 38
@@ -230,6 +231,31 @@ TD.align_top { vertical-align: top; }
230 return returnstruct; 231 return returnstruct;
231 } 232 }
232 233
234 /// <summary>
235 /// Return summar information in the form:
236 /// <pre>
237 /// {"totalUsers": "34",
238 /// "totalSessions": "233",
239 /// ...
240 /// }
241 /// </pre>
242 /// </summary>
243 /// <param name="pModelResult"></param>
244 /// <returns></returns>
245 public string RenderJson(Hashtable pModelResult) {
246 stats_default_page_values values = (stats_default_page_values) pModelResult["hdata"];
247
248 OSDMap summaryInfo = new OSDMap();
249 summaryInfo.Add("totalUsers", new OSDString(values.total_num_users.ToString()));
250 summaryInfo.Add("totalSessions", new OSDString(values.total_num_sessions.ToString()));
251 summaryInfo.Add("averageClientFPS", new OSDString(values.avg_client_fps.ToString()));
252 summaryInfo.Add("averageClientMem", new OSDString(values.avg_client_mem_use.ToString()));
253 summaryInfo.Add("averageSimFPS", new OSDString(values.avg_sim_fps.ToString()));
254 summaryInfo.Add("averagePingTime", new OSDString(values.avg_ping.ToString()));
255 summaryInfo.Add("totalKBOut", new OSDString(values.total_kb_out.ToString()));
256 summaryInfo.Add("totalKBIn", new OSDString(values.total_kb_in.ToString()));
257 return summaryInfo.ToString();
258 }
233 } 259 }
234 260
235 public struct stats_default_page_values 261 public struct stats_default_page_values
@@ -247,4 +273,5 @@ TD.align_top { vertical-align: top; }
247 public Dictionary<UUID, USimStatsData> sim_stat_data; 273 public Dictionary<UUID, USimStatsData> sim_stat_data;
248 public Dictionary<string, IStatsController> stats_reports; 274 public Dictionary<string, IStatsController> stats_reports;
249 } 275 }
276
250} 277}
diff --git a/OpenSim/Region/UserStatistics/HTMLUtil.cs b/OpenSim/Region/OptionalModules/UserStatistics/HTMLUtil.cs
index c07619f..c07619f 100644
--- a/OpenSim/Region/UserStatistics/HTMLUtil.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/HTMLUtil.cs
diff --git a/OpenSim/Region/UserStatistics/IStatsReport.cs b/OpenSim/Region/OptionalModules/UserStatistics/IStatsReport.cs
index e0ecce4..80c4487 100644
--- a/OpenSim/Region/UserStatistics/IStatsReport.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/IStatsReport.cs
@@ -34,5 +34,6 @@ namespace OpenSim.Region.UserStatistics
34 string ReportName { get; } 34 string ReportName { get; }
35 Hashtable ProcessModel(Hashtable pParams); 35 Hashtable ProcessModel(Hashtable pParams);
36 string RenderView(Hashtable pModelResult); 36 string RenderView(Hashtable pModelResult);
37 string RenderJson(Hashtable pModelResult);
37 } 38 }
38} 39}
diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/OptionalModules/UserStatistics/LogLinesAJAX.cs
index 74de46b..4d45b80 100644
--- a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/LogLinesAJAX.cs
@@ -33,6 +33,7 @@ using System.Text;
33using System.Text.RegularExpressions; 33using System.Text.RegularExpressions;
34using Mono.Data.SqliteClient; 34using Mono.Data.SqliteClient;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework.Monitoring; 38using OpenSim.Framework.Monitoring;
38 39
@@ -125,6 +126,34 @@ namespace OpenSim.Region.UserStatistics
125 return output.ToString(); 126 return output.ToString();
126 } 127 }
127 128
129 /// <summary>
130 /// Return the last log lines. Output in the format:
131 /// <pre>
132 /// {"logLines": [
133 /// "line1",
134 /// "line2",
135 /// ...
136 /// ]
137 /// }
138 /// </pre>
139 /// </summary>
140 /// <param name="pModelResult"></param>
141 /// <returns></returns>
142 public string RenderJson(Hashtable pModelResult)
143 {
144 OSDMap logInfo = new OpenMetaverse.StructuredData.OSDMap();
145
146 OSDArray logLines = new OpenMetaverse.StructuredData.OSDArray();
147 string tmp = normalizeEndLines.Replace(pModelResult["loglines"].ToString(), "\n");
148 string[] result = Regex.Split(tmp, "\n");
149 for (int i = 0; i < result.Length; i++)
150 {
151 logLines.Add(new OSDString(result[i]));
152 }
153 logInfo.Add("logLines", logLines);
154 return logInfo.ToString();
155 }
156
128 #endregion 157 #endregion
129 } 158 }
130} 159}
diff --git a/OpenSim/Region/UserStatistics/Prototype_distributor.cs b/OpenSim/Region/OptionalModules/UserStatistics/Prototype_distributor.cs
index 53ae557..6f8b2aa 100644
--- a/OpenSim/Region/UserStatistics/Prototype_distributor.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/Prototype_distributor.cs
@@ -36,7 +36,18 @@ namespace OpenSim.Region.UserStatistics
36{ 36{
37 public class Prototype_distributor : IStatsController 37 public class Prototype_distributor : IStatsController
38 { 38 {
39 private string prototypejs=string.Empty; 39 private string jsFileName = "prototype.js";
40 private string prototypejs = string.Empty;
41
42 public Prototype_distributor()
43 {
44 jsFileName = "prototype.js";
45 }
46
47 public Prototype_distributor(string jsName)
48 {
49 jsFileName = jsName;
50 }
40 51
41 public string ReportName 52 public string ReportName
42 { 53 {
@@ -45,20 +56,24 @@ namespace OpenSim.Region.UserStatistics
45 public Hashtable ProcessModel(Hashtable pParams) 56 public Hashtable ProcessModel(Hashtable pParams)
46 { 57 {
47 Hashtable pResult = new Hashtable(); 58 Hashtable pResult = new Hashtable();
48 if (prototypejs.Length == 0) 59 pResult["js"] = jsFileName;
60 return pResult;
61 }
62
63 public string RenderView(Hashtable pModelResult)
64 {
65 string fileName = (string)pModelResult["js"];
66 using (StreamReader fs = new StreamReader(new FileStream(Util.dataDir() + "/data/" + fileName, FileMode.Open)))
49 { 67 {
50 StreamReader fs = new StreamReader(new FileStream(Util.dataDir() + "/data/prototype.js", FileMode.Open));
51 prototypejs = fs.ReadToEnd(); 68 prototypejs = fs.ReadToEnd();
52 fs.Close(); 69 fs.Close();
53 fs.Dispose();
54 } 70 }
55 pResult["js"] = prototypejs; 71 return prototypejs;
56 return pResult;
57 } 72 }
58 73
59 public string RenderView(Hashtable pModelResult) 74 public string RenderJson(Hashtable pModelResult)
60 { 75 {
61 return pModelResult["js"].ToString(); 76 return "{}";
62 } 77 }
63 78
64 } 79 }
diff --git a/OpenSim/Region/UserStatistics/Sessions_Report.cs b/OpenSim/Region/OptionalModules/UserStatistics/Sessions_Report.cs
index 1a2d460..0e94912 100644
--- a/OpenSim/Region/UserStatistics/Sessions_Report.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/Sessions_Report.cs
@@ -278,6 +278,11 @@ TD.align_top { vertical-align: top; }
278 public DateTime start_time; 278 public DateTime start_time;
279 } 279 }
280 280
281 public string RenderJson(Hashtable pModelResult)
282 {
283 return "{}";
284 }
281 #endregion 285 #endregion
282 } 286 }
287
283} 288}
diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/OptionalModules/UserStatistics/SimStatsAJAX.cs
index 28051fb..06d9e91 100644
--- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/SimStatsAJAX.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32using System.Text; 32using System.Text;
33using Mono.Data.SqliteClient; 33using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
35using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
36using OpenSim.Framework.Monitoring; 37using OpenSim.Framework.Monitoring;
37 38
@@ -161,9 +162,6 @@ namespace OpenSim.Region.UserStatistics
161 output.Append("OthrMS"); 162 output.Append("OthrMS");
162 HTMLUtil.TD_C(ref output); 163 HTMLUtil.TD_C(ref output);
163 HTMLUtil.TD_O(ref output, TDHeaderClass); 164 HTMLUtil.TD_O(ref output, TDHeaderClass);
164 output.Append("ScrLPS");
165 HTMLUtil.TD_C(ref output);
166 HTMLUtil.TD_O(ref output, TDHeaderClass);
167 output.Append("OutPPS"); 165 output.Append("OutPPS");
168 HTMLUtil.TD_C(ref output); 166 HTMLUtil.TD_C(ref output);
169 HTMLUtil.TD_O(ref output, TDHeaderClass); 167 HTMLUtil.TD_O(ref output, TDHeaderClass);
@@ -193,9 +191,6 @@ namespace OpenSim.Region.UserStatistics
193 output.Append(sdata.OtherFrameTime); 191 output.Append(sdata.OtherFrameTime);
194 HTMLUtil.TD_C(ref output); 192 HTMLUtil.TD_C(ref output);
195 HTMLUtil.TD_O(ref output, TDDataClassCenter); 193 HTMLUtil.TD_O(ref output, TDDataClassCenter);
196 output.Append(sdata.ScriptLinesPerSecond);
197 HTMLUtil.TD_C(ref output);
198 HTMLUtil.TD_O(ref output, TDDataClassCenter);
199 output.Append(sdata.OutPacketsPerSecond); 194 output.Append(sdata.OutPacketsPerSecond);
200 HTMLUtil.TD_C(ref output); 195 HTMLUtil.TD_C(ref output);
201 HTMLUtil.TD_O(ref output, TDDataClassCenter); 196 HTMLUtil.TD_O(ref output, TDDataClassCenter);
@@ -218,6 +213,64 @@ namespace OpenSim.Region.UserStatistics
218 return output.ToString(); 213 return output.ToString();
219 } 214 }
220 215
216 /// <summary>
217 /// Return stat information for all regions in the sim. Returns data of the form:
218 /// <pre>
219 /// {"REGIONNAME": {
220 /// "region": "REGIONNAME",
221 /// "timeDilation": "101",
222 /// ... // the rest of the stat info
223 /// },
224 /// ... // entries for each region
225 /// }
226 /// </pre>
227 /// </summary>
228 /// <param name="pModelResult"></param>
229 /// <returns></returns>
230 public string RenderJson(Hashtable pModelResult)
231 {
232 List<Scene> all_scenes = (List<Scene>) pModelResult["hdata"];
233 Dictionary<UUID, USimStatsData> sdatadic = (Dictionary<UUID,USimStatsData>)pModelResult["simstats"];
234
235 OSDMap allStatsInfo = new OpenMetaverse.StructuredData.OSDMap();
236 foreach (USimStatsData sdata in sdatadic.Values)
237 {
238 OSDMap statsInfo = new OpenMetaverse.StructuredData.OSDMap();
239 string regionName = "unknown";
240 foreach (Scene sn in all_scenes)
241 {
242 if (sn.RegionInfo.RegionID == sdata.RegionId)
243 {
244 regionName = sn.RegionInfo.RegionName;
245 break;
246 }
247 }
248 statsInfo.Add("region", new OSDString(regionName));
249 statsInfo.Add("timeDilation", new OSDString(sdata.TimeDilation.ToString()));
250 statsInfo.Add("simFPS", new OSDString(sdata.SimFps.ToString()));
251 statsInfo.Add("physicsFPS", new OSDString(sdata.PhysicsFps.ToString()));
252 statsInfo.Add("agentUpdates", new OSDString(sdata.AgentUpdates.ToString()));
253 statsInfo.Add("rootAgents", new OSDString(sdata.RootAgents.ToString()));
254 statsInfo.Add("childAgents", new OSDString(sdata.ChildAgents.ToString()));
255 statsInfo.Add("totalPrims", new OSDString(sdata.TotalPrims.ToString()));
256 statsInfo.Add("activePrims", new OSDString(sdata.ActivePrims.ToString()));
257 statsInfo.Add("activeScripts", new OSDString(sdata.ActiveScripts.ToString()));
258 statsInfo.Add("scriptLinesPerSec", new OSDString(sdata.ScriptLinesPerSecond.ToString()));
259 statsInfo.Add("totalFrameTime", new OSDString(sdata.TotalFrameTime.ToString()));
260 statsInfo.Add("agentFrameTime", new OSDString(sdata.AgentFrameTime.ToString()));
261 statsInfo.Add("physicsFrameTime", new OSDString(sdata.PhysicsFrameTime.ToString()));
262 statsInfo.Add("otherFrameTime", new OSDString(sdata.OtherFrameTime.ToString()));
263 statsInfo.Add("outPacketsPerSec", new OSDString(sdata.OutPacketsPerSecond.ToString()));
264 statsInfo.Add("inPacketsPerSec", new OSDString(sdata.InPacketsPerSecond.ToString()));
265 statsInfo.Add("unackedByptes", new OSDString(sdata.UnackedBytes.ToString()));
266 statsInfo.Add("pendingDownloads", new OSDString(sdata.PendingDownloads.ToString()));
267 statsInfo.Add("pendingUploads", new OSDString(sdata.PendingUploads.ToString()));
268
269 allStatsInfo.Add(regionName, statsInfo);
270 }
271 return allStatsInfo.ToString();
272 }
273
221 #endregion 274 #endregion
222 } 275 }
223} 276}
diff --git a/OpenSim/Region/UserStatistics/Updater_distributor.cs b/OpenSim/Region/OptionalModules/UserStatistics/Updater_distributor.cs
index 9593cc9..601e06b 100644
--- a/OpenSim/Region/UserStatistics/Updater_distributor.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/Updater_distributor.cs
@@ -62,5 +62,9 @@ namespace OpenSim.Region.UserStatistics
62 return pModelResult["js"].ToString(); 62 return pModelResult["js"].ToString();
63 } 63 }
64 64
65 public string RenderJson(Hashtable pModelResult) {
66 return "{}";
67 }
68
65 } 69 }
66} \ No newline at end of file 70} \ No newline at end of file
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs
index 64cb577..bcb6361 100644
--- a/OpenSim/Region/UserStatistics/WebStatsModule.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs
@@ -50,9 +50,6 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
50using OSD = OpenMetaverse.StructuredData.OSD; 50using OSD = OpenMetaverse.StructuredData.OSD;
51using OSDMap = OpenMetaverse.StructuredData.OSDMap; 51using OSDMap = OpenMetaverse.StructuredData.OSDMap;
52 52
53[assembly: Addin("WebStats", "1.0")]
54[assembly: AddinDependency("OpenSim", "0.5")]
55
56namespace OpenSim.Region.UserStatistics 53namespace OpenSim.Region.UserStatistics
57{ 54{
58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebStatsModule")] 55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebStatsModule")]
@@ -121,6 +118,10 @@ namespace OpenSim.Region.UserStatistics
121 reports.Add("clients.report", clientReport); 118 reports.Add("clients.report", clientReport);
122 reports.Add("sessions.report", sessionsReport); 119 reports.Add("sessions.report", sessionsReport);
123 120
121 reports.Add("sim.css", new Prototype_distributor("sim.css"));
122 reports.Add("sim.html", new Prototype_distributor("sim.html"));
123 reports.Add("jquery.js", new Prototype_distributor("jquery.js"));
124
124 //// 125 ////
125 // Add Your own Reports here (Do Not Modify Lines here Devs!) 126 // Add Your own Reports here (Do Not Modify Lines here Devs!)
126 //// 127 ////
@@ -255,9 +256,12 @@ namespace OpenSim.Region.UserStatistics
255 string regpath = request["uri"].ToString(); 256 string regpath = request["uri"].ToString();
256 int response_code = 404; 257 int response_code = 404;
257 string contenttype = "text/html"; 258 string contenttype = "text/html";
259 bool jsonFormatOutput = false;
258 260
259 string strOut = string.Empty; 261 string strOut = string.Empty;
260 262
263 // The request patch should be "/SStats/reportName" where 'reportName'
264 // is one of the names added to the 'reports' hashmap.
261 regpath = regpath.Remove(0, 8); 265 regpath = regpath.Remove(0, 8);
262 if (regpath.Length == 0) regpath = "default.report"; 266 if (regpath.Length == 0) regpath = "default.report";
263 if (reports.ContainsKey(regpath)) 267 if (reports.ContainsKey(regpath))
@@ -265,6 +269,9 @@ namespace OpenSim.Region.UserStatistics
265 IStatsController rep = reports[regpath]; 269 IStatsController rep = reports[regpath];
266 Hashtable repParams = new Hashtable(); 270 Hashtable repParams = new Hashtable();
267 271
272 if (request.ContainsKey("json"))
273 jsonFormatOutput = true;
274
268 if (request.ContainsKey("requestvars")) 275 if (request.ContainsKey("requestvars"))
269 repParams["RequestVars"] = request["requestvars"]; 276 repParams["RequestVars"] = request["requestvars"];
270 else 277 else
@@ -284,13 +291,26 @@ namespace OpenSim.Region.UserStatistics
284 291
285 concurrencyCounter++; 292 concurrencyCounter++;
286 293
287 strOut = rep.RenderView(rep.ProcessModel(repParams)); 294 if (jsonFormatOutput)
295 {
296 strOut = rep.RenderJson(rep.ProcessModel(repParams));
297 contenttype = "text/json";
298 }
299 else
300 {
301 strOut = rep.RenderView(rep.ProcessModel(repParams));
302 }
288 303
289 if (regpath.EndsWith("js")) 304 if (regpath.EndsWith("js"))
290 { 305 {
291 contenttype = "text/javascript"; 306 contenttype = "text/javascript";
292 } 307 }
293 308
309 if (regpath.EndsWith("css"))
310 {
311 contenttype = "text/css";
312 }
313
294 concurrencyCounter--; 314 concurrencyCounter--;
295 315
296 response_code = 200; 316 response_code = 200;
@@ -397,7 +417,7 @@ namespace OpenSim.Region.UserStatistics
397 Encoding encoding = Encoding.ASCII; 417 Encoding encoding = Encoding.ASCII;
398 int sizeOfChar = encoding.GetByteCount("\n"); 418 int sizeOfChar = encoding.GetByteCount("\n");
399 byte[] buffer = encoding.GetBytes("\n"); 419 byte[] buffer = encoding.GetBytes("\n");
400 string logfile = Util.logDir() + "/" + "OpenSim.log"; 420 string logfile = Util.logFile();
401 FileStream fs = new FileStream(logfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 421 FileStream fs = new FileStream(logfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
402 Int64 tokenCount = 0; 422 Int64 tokenCount = 0;
403 Int64 endPosition = fs.Length / sizeOfChar; 423 Int64 endPosition = fs.Length / sizeOfChar;
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/CameraOnlyModeModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/CameraOnlyModeModule.cs
new file mode 100644
index 0000000..7ae4223
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/CameraOnlyModeModule.cs
@@ -0,0 +1,176 @@
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.IO;
30using System.Reflection;
31using System.Text;
32using System.Collections.Generic;
33using System.Threading;
34
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim;
38using OpenSim.Region;
39using OpenSim.Region.Framework;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Framework;
43//using OpenSim.Framework.Capabilities;
44using OpenSim.Framework.Servers;
45using OpenSim.Framework.Servers.HttpServer;
46using Nini.Config;
47using log4net;
48using Mono.Addins;
49using OSDMap = OpenMetaverse.StructuredData.OSDMap;
50using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags;
51
52namespace OpenSim.Region.OptionalModules.ViewerSupport
53{
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CameraOnlyMode")]
55 public class CameraOnlyModeModule : INonSharedRegionModule
56 {
57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58
59 private Scene m_scene;
60 private SimulatorFeaturesHelper m_Helper;
61 private bool m_Enabled;
62 private int m_UserLevel;
63
64 public string Name
65 {
66 get { return "CameraOnlyModeModule"; }
67 }
68
69 public Type ReplaceableInterface
70 {
71 get { return null; }
72 }
73
74 public void Initialise(IConfigSource config)
75 {
76 IConfig moduleConfig = config.Configs["CameraOnlyModeModule"];
77 if (moduleConfig != null)
78 {
79 m_Enabled = moduleConfig.GetBoolean("enabled", false);
80 if (m_Enabled)
81 {
82 m_UserLevel = moduleConfig.GetInt("UserLevel", 0);
83 m_log.Info("[CAMERA-ONLY MODE]: CameraOnlyModeModule enabled");
84 }
85
86 }
87 }
88
89 public void Close()
90 {
91 }
92
93 public void AddRegion(Scene scene)
94 {
95 if (m_Enabled)
96 {
97 m_scene = scene;
98 //m_scene.EventManager.OnMakeRootAgent += (OnMakeRootAgent);
99 }
100 }
101
102 //private void OnMakeRootAgent(ScenePresence obj)
103 //{
104 // throw new NotImplementedException();
105 //}
106
107 public void RegionLoaded(Scene scene)
108 {
109 if (m_Enabled)
110 {
111 IEntityTransferModule et = m_scene.RequestModuleInterface<IEntityTransferModule>();
112 m_Helper = new SimulatorFeaturesHelper(scene, et);
113
114 ISimulatorFeaturesModule featuresModule = m_scene.RequestModuleInterface<ISimulatorFeaturesModule>();
115 if (featuresModule != null)
116 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
117 }
118 }
119
120 public void RemoveRegion(Scene scene)
121 {
122 }
123
124 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
125 {
126 m_log.DebugFormat("[CAMERA-ONLY MODE]: OnSimulatorFeaturesRequest in {0}", m_scene.RegionInfo.RegionName);
127 if (m_Helper.ShouldSend(agentID) && m_Helper.UserLevel(agentID) <= m_UserLevel)
128 {
129 OSDMap extrasMap;
130 if (features.ContainsKey("OpenSimExtras"))
131 {
132 extrasMap = (OSDMap)features["OpenSimExtras"];
133 }
134 else
135 {
136 extrasMap = new OSDMap();
137 features["OpenSimExtras"] = extrasMap;
138 }
139 extrasMap["camera-only-mode"] = OSDMap.FromString("true");
140 m_log.DebugFormat("[CAMERA-ONLY MODE]: Sent in {0}", m_scene.RegionInfo.RegionName);
141
142 // Detaching attachments doesn't work for HG visitors,
143 // so I'm giving that up.
144 //Util.FireAndForget(delegate { DetachAttachments(agentID); });
145 }
146 else
147 m_log.DebugFormat("[CAMERA-ONLY MODE]: NOT Sending camera-only-mode in {0}", m_scene.RegionInfo.RegionName);
148 }
149
150 private void DetachAttachments(UUID agentID)
151 {
152 ScenePresence sp = m_scene.GetScenePresence(agentID);
153 if ((sp.TeleportFlags & TeleportFlags.ViaLogin) != 0)
154 // Wait a little, cos there's weird stuff going on at login related to
155 // the Current Outfit Folder
156 Thread.Sleep(8000);
157
158 if (sp != null && m_scene.AttachmentsModule != null)
159 {
160 List<SceneObjectGroup> attachs = sp.GetAttachments();
161 if (attachs != null && attachs.Count > 0)
162 {
163 foreach (SceneObjectGroup sog in attachs)
164 {
165 m_log.DebugFormat("[CAMERA-ONLY MODE]: Forcibly detaching attach {0} from {1} in {2}",
166 sog.Name, sp.Name, m_scene.RegionInfo.RegionName);
167
168 m_scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, sog);
169 }
170 }
171 }
172 }
173
174 }
175
176}
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicFloaterModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicFloaterModule.cs
new file mode 100644
index 0000000..e76e8f2
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicFloaterModule.cs
@@ -0,0 +1,238 @@
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.IO;
30using System.Reflection;
31using System.Text;
32using System.Collections.Generic;
33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35using OpenSim;
36using OpenSim.Region;
37using OpenSim.Region.Framework;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using Nini.Config;
44using log4net;
45using Mono.Addins;
46using Caps = OpenSim.Framework.Capabilities.Caps;
47using OSDMap = OpenMetaverse.StructuredData.OSDMap;
48
49namespace OpenSim.Region.OptionalModules.ViewerSupport
50{
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DynamicFloater")]
52 public class DynamicFloaterModule : INonSharedRegionModule, IDynamicFloaterModule
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 private Scene m_scene;
57
58 private Dictionary<UUID, Dictionary<int, FloaterData>> m_floaters = new Dictionary<UUID, Dictionary<int, FloaterData>>();
59
60 public string Name
61 {
62 get { return "DynamicFloaterModule"; }
63 }
64
65 public Type ReplaceableInterface
66 {
67 get { return null; }
68 }
69
70 public void Initialise(IConfigSource config)
71 {
72 }
73
74 public void Close()
75 {
76 }
77
78 public void AddRegion(Scene scene)
79 {
80 m_scene = scene;
81 scene.EventManager.OnNewClient += OnNewClient;
82 scene.EventManager.OnClientClosed += OnClientClosed;
83 m_scene.RegisterModuleInterface<IDynamicFloaterModule>(this);
84 }
85
86 public void RegionLoaded(Scene scene)
87 {
88 }
89
90 public void RemoveRegion(Scene scene)
91 {
92 }
93
94 private void OnNewClient(IClientAPI client)
95 {
96 client.OnChatFromClient += OnChatFromClient;
97 }
98
99 private void OnClientClosed(UUID agentID, Scene scene)
100 {
101 m_floaters.Remove(agentID);
102 }
103
104 private void SendToClient(ScenePresence sp, string msg)
105 {
106 sp.ControllingClient.SendChatMessage(msg,
107 (byte)ChatTypeEnum.Owner,
108 sp.AbsolutePosition,
109 "Server",
110 UUID.Zero,
111 UUID.Zero,
112 (byte)ChatSourceType.Object,
113 (byte)ChatAudibleLevel.Fully);
114 }
115
116 public void DoUserFloater(UUID agentID, FloaterData dialogData, string configuration)
117 {
118 ScenePresence sp = m_scene.GetScenePresence(agentID);
119 if (sp == null || sp.IsChildAgent)
120 return;
121
122 if (!m_floaters.ContainsKey(agentID))
123 m_floaters[agentID] = new Dictionary<int, FloaterData>();
124
125 if (m_floaters[agentID].ContainsKey(dialogData.Channel))
126 return;
127
128 m_floaters[agentID].Add(dialogData.Channel, dialogData);
129
130 string xml;
131 if (dialogData.XmlText != null && dialogData.XmlText != String.Empty)
132 {
133 xml = dialogData.XmlText;
134 }
135 else
136 {
137 using (FileStream fs = File.Open(dialogData.XmlName + ".xml", FileMode.Open))
138 {
139 using (StreamReader sr = new StreamReader(fs))
140 xml = sr.ReadToEnd().Replace("\n", "");
141 }
142 }
143
144 List<string> xparts = new List<string>();
145
146 while (xml.Length > 0)
147 {
148 string x = xml;
149 if (x.Length > 600)
150 {
151 x = x.Substring(0, 600);
152 xml = xml.Substring(600);
153 }
154 else
155 {
156 xml = String.Empty;
157 }
158
159 xparts.Add(x);
160 }
161
162 for (int i = 0 ; i < xparts.Count ; i++)
163 SendToClient(sp, String.Format("># floater {2} create {0}/{1} " + xparts[i], i + 1, xparts.Count, dialogData.FloaterName));
164
165 SendToClient(sp, String.Format("># floater {0} {{notify:1}} {{channel: {1}}} {{node:cancel {{notify:1}}}} {{node:ok {{notify:1}}}} {2}", dialogData.FloaterName, (uint)dialogData.Channel, configuration));
166 }
167
168 private void OnChatFromClient(object sender, OSChatMessage msg)
169 {
170 if (msg.Sender == null)
171 return;
172
173 //m_log.DebugFormat("chan {0} msg {1}", msg.Channel, msg.Message);
174
175 IClientAPI client = msg.Sender;
176
177 if (!m_floaters.ContainsKey(client.AgentId))
178 return;
179
180 string[] parts = msg.Message.Split(new char[] {':'});
181 if (parts.Length == 0)
182 return;
183
184 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
185 if (sp == null || sp.IsChildAgent)
186 return;
187
188 Dictionary<int, FloaterData> d = m_floaters[client.AgentId];
189
190 // Work around a viewer bug - VALUE from any
191 // dialog can appear on this channel and needs to
192 // be dispatched to ALL open dialogs for the user
193 if (msg.Channel == 427169570)
194 {
195 if (parts[0] == "VALUE")
196 {
197 foreach (FloaterData dd in d.Values)
198 {
199 if(dd.Handler(client, dd, parts))
200 {
201 m_floaters[client.AgentId].Remove(dd.Channel);
202 SendToClient(sp, String.Format("># floater {0} destroy", dd.FloaterName));
203 break;
204 }
205 }
206 }
207 return;
208 }
209
210 if (!d.ContainsKey(msg.Channel))
211 return;
212
213 FloaterData data = d[msg.Channel];
214
215 if (parts[0] == "NOTIFY")
216 {
217 if (parts[1] == "cancel" || parts[1] == data.FloaterName)
218 {
219 m_floaters[client.AgentId].Remove(data.Channel);
220 SendToClient(sp, String.Format("># floater {0} destroy", data.FloaterName));
221 }
222 }
223
224 if (data.Handler != null && data.Handler(client, data, parts))
225 {
226 m_floaters[client.AgentId].Remove(data.Channel);
227 SendToClient(sp, String.Format("># floater {0} destroy", data.FloaterName));
228 }
229 }
230
231 public void FloaterControl(ScenePresence sp, FloaterData d, string msg)
232 {
233 string sendData = String.Format("># floater {0} {1}", d.FloaterName, msg);
234 SendToClient(sp, sendData);
235
236 }
237 }
238}
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
new file mode 100644
index 0000000..d37369c
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
@@ -0,0 +1,304 @@
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.IO;
30using System.Reflection;
31using System.Text;
32using System.Collections.Generic;
33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35using OpenSim;
36using OpenSim.Region;
37using OpenSim.Region.Framework;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Framework;
41//using OpenSim.Framework.Capabilities;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using Nini.Config;
45using log4net;
46using Mono.Addins;
47using Caps = OpenSim.Framework.Capabilities.Caps;
48using OSDMap = OpenMetaverse.StructuredData.OSDMap;
49
50namespace OpenSim.Region.OptionalModules.ViewerSupport
51{
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DynamicMenu")]
53 public class DynamicMenuModule : INonSharedRegionModule, IDynamicMenuModule
54 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 private class MenuItemData
58 {
59 public string Title;
60 public UUID AgentID;
61 public InsertLocation Location;
62 public UserMode Mode;
63 public CustomMenuHandler Handler;
64 }
65
66 private Dictionary<UUID, List<MenuItemData>> m_menuItems =
67 new Dictionary<UUID, List<MenuItemData>>();
68
69 private Scene m_scene;
70
71 public string Name
72 {
73 get { return "DynamicMenuModule"; }
74 }
75
76 public Type ReplaceableInterface
77 {
78 get { return null; }
79 }
80
81 public void Initialise(IConfigSource config)
82 {
83 }
84
85 public void Close()
86 {
87 }
88
89 public void AddRegion(Scene scene)
90 {
91 m_scene = scene;
92 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
93 m_scene.RegisterModuleInterface<IDynamicMenuModule>(this);
94 }
95
96 public void RegionLoaded(Scene scene)
97 {
98 ISimulatorFeaturesModule featuresModule = m_scene.RequestModuleInterface<ISimulatorFeaturesModule>();
99
100 if (featuresModule != null)
101 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
102 }
103
104 public void RemoveRegion(Scene scene)
105 {
106 }
107
108 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
109 {
110 OSD menus = new OSDMap();
111 if (features.ContainsKey("menus"))
112 menus = features["menus"];
113
114 OSDMap agent = new OSDMap();
115 OSDMap world = new OSDMap();
116 OSDMap tools = new OSDMap();
117 OSDMap advanced = new OSDMap();
118 OSDMap admin = new OSDMap();
119 if (((OSDMap)menus).ContainsKey("agent"))
120 agent = (OSDMap)((OSDMap)menus)["agent"];
121 if (((OSDMap)menus).ContainsKey("world"))
122 world = (OSDMap)((OSDMap)menus)["world"];
123 if (((OSDMap)menus).ContainsKey("tools"))
124 tools = (OSDMap)((OSDMap)menus)["tools"];
125 if (((OSDMap)menus).ContainsKey("advanced"))
126 advanced = (OSDMap)((OSDMap)menus)["advanced"];
127 if (((OSDMap)menus).ContainsKey("admin"))
128 admin = (OSDMap)((OSDMap)menus)["admin"];
129
130 if (m_menuItems.ContainsKey(UUID.Zero))
131 {
132 foreach (MenuItemData d in m_menuItems[UUID.Zero])
133 {
134 if (d.Mode == UserMode.God && (!m_scene.Permissions.IsGod(agentID)))
135 continue;
136
137 OSDMap loc = null;
138 switch (d.Location)
139 {
140 case InsertLocation.Agent:
141 loc = agent;
142 break;
143 case InsertLocation.World:
144 loc = world;
145 break;
146 case InsertLocation.Tools:
147 loc = tools;
148 break;
149 case InsertLocation.Advanced:
150 loc = advanced;
151 break;
152 case InsertLocation.Admin:
153 loc = admin;
154 break;
155 }
156
157 if (loc == null)
158 continue;
159
160 loc[d.Title] = OSD.FromString(d.Title);
161 }
162 }
163
164 if (m_menuItems.ContainsKey(agentID))
165 {
166 foreach (MenuItemData d in m_menuItems[agentID])
167 {
168 if (d.Mode == UserMode.God && (!m_scene.Permissions.IsGod(agentID)))
169 continue;
170
171 OSDMap loc = null;
172 switch (d.Location)
173 {
174 case InsertLocation.Agent:
175 loc = agent;
176 break;
177 case InsertLocation.World:
178 loc = world;
179 break;
180 case InsertLocation.Tools:
181 loc = tools;
182 break;
183 case InsertLocation.Advanced:
184 loc = advanced;
185 break;
186 case InsertLocation.Admin:
187 loc = admin;
188 break;
189 }
190
191 if (loc == null)
192 continue;
193
194 loc[d.Title] = OSD.FromString(d.Title);
195 }
196 }
197
198
199 ((OSDMap)menus)["agent"] = agent;
200 ((OSDMap)menus)["world"] = world;
201 ((OSDMap)menus)["tools"] = tools;
202 ((OSDMap)menus)["advanced"] = advanced;
203 ((OSDMap)menus)["admin"] = admin;
204
205 features["menus"] = menus;
206 }
207
208 private void OnRegisterCaps(UUID agentID, Caps caps)
209 {
210 string capUrl = "/CAPS/" + UUID.Random() + "/";
211
212 capUrl = "/CAPS/" + UUID.Random() + "/";
213 caps.RegisterHandler("CustomMenuAction", new MenuActionHandler(capUrl, "CustomMenuAction", agentID, this, m_scene));
214 }
215
216 internal void HandleMenuSelection(string action, UUID agentID, List<uint> selection)
217 {
218 if (m_menuItems.ContainsKey(agentID))
219 {
220 foreach (MenuItemData d in m_menuItems[agentID])
221 {
222 if (d.Title == action)
223 d.Handler(action, agentID, selection);
224 }
225 }
226
227 if (m_menuItems.ContainsKey(UUID.Zero))
228 {
229 foreach (MenuItemData d in m_menuItems[UUID.Zero])
230 {
231 if (d.Title == action)
232 d.Handler(action, agentID, selection);
233 }
234 }
235 }
236
237 public void AddMenuItem(string title, InsertLocation location, UserMode mode, CustomMenuHandler handler)
238 {
239 AddMenuItem(UUID.Zero, title, location, mode, handler);
240 }
241
242 public void AddMenuItem(UUID agentID, string title, InsertLocation location, UserMode mode, CustomMenuHandler handler)
243 {
244 if (!m_menuItems.ContainsKey(agentID))
245 m_menuItems[agentID] = new List<MenuItemData>();
246
247 m_menuItems[agentID].Add(new MenuItemData() { Title = title, AgentID = agentID, Location = location, Mode = mode, Handler = handler });
248 }
249
250 public void RemoveMenuItem(string action)
251 {
252 foreach (KeyValuePair<UUID,List< MenuItemData>> kvp in m_menuItems)
253 {
254 List<MenuItemData> pendingDeletes = new List<MenuItemData>();
255 foreach (MenuItemData d in kvp.Value)
256 {
257 if (d.Title == action)
258 pendingDeletes.Add(d);
259 }
260
261 foreach (MenuItemData d in pendingDeletes)
262 kvp.Value.Remove(d);
263 }
264 }
265 }
266
267 public class MenuActionHandler : BaseStreamHandler
268 {
269 private static readonly ILog m_log =
270 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
271
272 private UUID m_agentID;
273 private Scene m_scene;
274 private DynamicMenuModule m_module;
275
276 public MenuActionHandler(string path, string name, UUID agentID, DynamicMenuModule module, Scene scene)
277 :base("POST", path, name, agentID.ToString())
278 {
279 m_agentID = agentID;
280 m_scene = scene;
281 m_module = module;
282 }
283
284 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
285 {
286 StreamReader reader = new StreamReader(request);
287 string requestBody = reader.ReadToEnd();
288
289 OSD osd = OSDParser.DeserializeLLSDXml(requestBody);
290
291 string action = ((OSDMap)osd)["action"].AsString();
292 OSDArray selection = (OSDArray)((OSDMap)osd)["selection"];
293 List<uint> sel = new List<uint>();
294 for (int i = 0 ; i < selection.Count ; i++)
295 sel.Add(selection[i].AsUInteger());
296
297 Util.FireAndForget(
298 x => { m_module.HandleMenuSelection(action, m_agentID, sel); }, null, "DynamicMenuModule.HandleMenuSelection");
299
300 Encoding encoding = Encoding.UTF8;
301 return encoding.GetBytes(OSDParser.SerializeLLSDXmlString(new OSD()));
302 }
303 }
304}
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/GodNamesModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/GodNamesModule.cs
new file mode 100644
index 0000000..e0537a4
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/GodNamesModule.cs
@@ -0,0 +1,144 @@
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.Reflection;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39
40namespace OpenSim.Region.OptionalModules.ViewerSupport
41{
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodNamesModule")]
43 public class GodNamesModule : ISharedRegionModule
44 {
45 // Infrastructure
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 // Configuration
49 private static bool m_enabled = false;
50 private static List<String> m_lastNames = new List<String>();
51 private static List<String> m_fullNames = new List<String>();
52
53 public void Initialise(IConfigSource config)
54 {
55 IConfig moduleConfig = config.Configs["GodNames"];
56
57 if (moduleConfig == null) {
58 return;
59 }
60
61 if (!moduleConfig.GetBoolean("Enabled", false)) {
62 m_log.Info("[GODNAMES]: Addon is disabled");
63 return;
64 }
65
66 m_log.Info("[GODNAMES]: Enabled");
67 m_enabled = true;
68 string conf_str = moduleConfig.GetString("FullNames", String.Empty);
69 foreach (string strl in conf_str.Split(',')) {
70 string strlan = strl.Trim(" \t".ToCharArray());
71 m_log.DebugFormat("[GODNAMES]: Adding {0} as a God name", strlan);
72 m_fullNames.Add(strlan);
73 }
74
75 conf_str = moduleConfig.GetString("Surnames", String.Empty);
76 foreach (string strl in conf_str.Split(',')) {
77 string strlan = strl.Trim(" \t".ToCharArray());
78 m_log.DebugFormat("[GODNAMES]: Adding {0} as a God last name", strlan);
79 m_lastNames.Add(strlan);
80 }
81 }
82
83 public void AddRegion(Scene scene) {
84 /*no op*/
85 }
86
87 public void RemoveRegion(Scene scene) {
88 /*no op*/
89 }
90
91 public void PostInitialise() {
92 /*no op*/
93 }
94
95 public void Close() {
96 /*no op*/
97 }
98
99 public Type ReplaceableInterface {
100 get { return null; }
101 }
102
103 public string Name {
104 get { return "Godnames"; }
105 }
106
107 public bool IsSharedModule {
108 get { return true; }
109 }
110
111 public virtual void RegionLoaded(Scene scene)
112 {
113 if (!m_enabled)
114 return;
115
116 ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
117
118 if (featuresModule != null)
119 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
120
121 }
122
123 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
124 {
125 OSD namesmap = new OSDMap();
126 if (features.ContainsKey("god_names"))
127 namesmap = features["god_names"];
128 else
129 features["god_names"] = namesmap;
130
131 OSDArray fnames = new OSDArray();
132 foreach (string name in m_fullNames) {
133 fnames.Add(name);
134 }
135 ((OSDMap)namesmap)["full_names"] = fnames;
136
137 OSDArray lnames = new OSDArray();
138 foreach (string name in m_lastNames) {
139 lnames.Add(name);
140 }
141 ((OSDMap)namesmap)["last_names"] = lnames;
142 }
143 }
144}
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs b/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs
new file mode 100644
index 0000000..2661522
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs
@@ -0,0 +1,171 @@
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.IO;
30using System.Reflection;
31using System.Text;
32using System.Collections.Generic;
33using System.Threading;
34
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim;
38using OpenSim.Region;
39using OpenSim.Region.Framework;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Framework;
43using OpenSim.Services.Interfaces;
44//using OpenSim.Framework.Capabilities;
45using Nini.Config;
46using log4net;
47using OSDMap = OpenMetaverse.StructuredData.OSDMap;
48using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags;
49
50namespace OpenSim.Region.OptionalModules.ViewerSupport
51{
52 public class SimulatorFeaturesHelper
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 private IEntityTransferModule m_TransferModule;
57 private Scene m_scene;
58
59 private struct RegionSend {
60 public UUID region;
61 public bool send;
62 };
63 // Using a static cache so that we don't have to perform the time-consuming tests
64 // in ShouldSend on Extra SimFeatures that go on the same response but come from
65 // different modules.
66 // This cached is indexed on the agentID and maps to a list of regions
67 private static ExpiringCache<UUID, List<RegionSend>> m_Cache = new ExpiringCache<UUID, List<RegionSend>>();
68 private const double TIMEOUT = 1.0; // time in cache
69
70 public SimulatorFeaturesHelper(Scene scene, IEntityTransferModule et)
71 {
72 m_scene = scene;
73 m_TransferModule = et;
74 }
75
76 public bool ShouldSend(UUID agentID)
77 {
78 List<RegionSend> rsendlist;
79 RegionSend rsend;
80 if (m_Cache.TryGetValue(agentID, out rsendlist))
81 {
82 rsend = rsendlist.Find(r => r.region == m_scene.RegionInfo.RegionID);
83 if (rsend.region != UUID.Zero) // Found it
84 {
85 return rsend.send;
86 }
87 }
88
89 // Relatively complex logic for deciding whether to send the extra SimFeature or not.
90 // This is because the viewer calls this cap to all sims that it knows about,
91 // including the departing sims and non-neighbors (those that are cached).
92 rsend.region = m_scene.RegionInfo.RegionID;
93 rsend.send = false;
94 IClientAPI client = null;
95 int counter = 200;
96
97 // Let's wait a little to see if we get a client here
98 while (!m_scene.TryGetClient(agentID, out client) && counter-- > 0)
99 Thread.Sleep(50);
100
101 if (client != null)
102 {
103 ScenePresence sp = WaitGetScenePresence(agentID);
104
105 if (sp != null)
106 {
107 // On the receiving region, the call to this cap may arrive before
108 // the agent is root. Make sure we only proceed from here when the agent
109 // has been made root
110 counter = 200;
111 while ((sp.IsInTransit || sp.IsChildAgent) && counter-- > 0)
112 {
113 Thread.Sleep(50);
114 }
115
116 // The viewer calls this cap on the departing sims too. Make sure
117 // that we only proceed after the agent is not in transit anymore.
118 // The agent must be root and not going anywhere
119 if (!sp.IsChildAgent && !m_TransferModule.IsInTransit(agentID))
120 rsend.send = true;
121
122 }
123 }
124 //else
125 // m_log.DebugFormat("[XXX]: client is null");
126
127
128 if (rsendlist == null)
129 {
130 rsendlist = new List<RegionSend>();
131 m_Cache.AddOrUpdate(agentID, rsendlist, TIMEOUT);
132 }
133 rsendlist.Add(rsend);
134
135 return rsend.send;
136 }
137
138 public int UserLevel(UUID agentID)
139 {
140 int level = 0;
141 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID);
142 if (account != null)
143 level = account.UserLevel;
144
145 return level;
146 }
147
148 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
149 {
150 int ntimes = 20;
151 ScenePresence sp = null;
152 while ((sp = m_scene.GetScenePresence(agentID)) == null && (ntimes-- > 0))
153 Thread.Sleep(1000);
154
155 if (sp == null)
156 m_log.WarnFormat(
157 "[XXX]: Did not find presence with id {0} in {1} before timeout",
158 agentID, m_scene.RegionInfo.RegionName);
159 else
160 {
161 ntimes = 10;
162 while (sp.IsInTransit && (ntimes-- > 0))
163 Thread.Sleep(1000);
164 }
165
166 return sp;
167 }
168
169 }
170
171}
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/SpecialUIModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/SpecialUIModule.cs
new file mode 100644
index 0000000..3fe922d
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/SpecialUIModule.cs
@@ -0,0 +1,165 @@
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.IO;
30using System.Reflection;
31using System.Text;
32using System.Collections.Generic;
33using System.Threading;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim;
37using OpenSim.Region;
38using OpenSim.Region.Framework;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Framework;
42//using OpenSim.Framework.Capabilities;
43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer;
45using Nini.Config;
46using log4net;
47using Mono.Addins;
48using OSDMap = OpenMetaverse.StructuredData.OSDMap;
49using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags;
50
51namespace OpenSim.Region.OptionalModules.ViewerSupport
52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SpecialUI")]
54 public class SpecialUIModule : INonSharedRegionModule
55 {
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57 private const string VIEWER_SUPPORT_DIR = "ViewerSupport";
58
59 private Scene m_scene;
60 private SimulatorFeaturesHelper m_Helper;
61 private bool m_Enabled;
62 private int m_UserLevel;
63
64 public string Name
65 {
66 get { return "SpecialUIModule"; }
67 }
68
69 public Type ReplaceableInterface
70 {
71 get { return null; }
72 }
73
74 public void Initialise(IConfigSource config)
75 {
76 IConfig moduleConfig = config.Configs["SpecialUIModule"];
77 if (moduleConfig != null)
78 {
79 m_Enabled = moduleConfig.GetBoolean("enabled", false);
80 if (m_Enabled)
81 {
82 m_UserLevel = moduleConfig.GetInt("UserLevel", 0);
83 m_log.Info("[SPECIAL UI]: SpecialUIModule enabled");
84 }
85
86 }
87 }
88
89 public void Close()
90 {
91 }
92
93 public void AddRegion(Scene scene)
94 {
95 if (m_Enabled)
96 {
97 m_scene = scene;
98 }
99 }
100
101 public void RegionLoaded(Scene scene)
102 {
103 if (m_Enabled)
104 {
105 IEntityTransferModule et = m_scene.RequestModuleInterface<IEntityTransferModule>();
106 m_Helper = new SimulatorFeaturesHelper(scene, et);
107
108 ISimulatorFeaturesModule featuresModule = m_scene.RequestModuleInterface<ISimulatorFeaturesModule>();
109 if (featuresModule != null)
110 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
111 }
112 }
113
114 public void RemoveRegion(Scene scene)
115 {
116 }
117
118 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
119 {
120 m_log.DebugFormat("[SPECIAL UI]: OnSimulatorFeaturesRequest in {0}", m_scene.RegionInfo.RegionName);
121 if (m_Helper.ShouldSend(agentID) && m_Helper.UserLevel(agentID) <= m_UserLevel)
122 {
123 OSDMap extrasMap;
124 OSDMap specialUI = new OSDMap();
125 using (StreamReader s = new StreamReader(Path.Combine(VIEWER_SUPPORT_DIR, "panel_toolbar.xml")))
126 {
127 if (features.ContainsKey("OpenSimExtras"))
128 extrasMap = (OSDMap)features["OpenSimExtras"];
129 else
130 {
131 extrasMap = new OSDMap();
132 features["OpenSimExtras"] = extrasMap;
133 }
134
135 specialUI["toolbar"] = OSDMap.FromString(s.ReadToEnd());
136 extrasMap["special-ui"] = specialUI;
137 }
138 m_log.DebugFormat("[SPECIAL UI]: Sending panel_toolbar.xml in {0}", m_scene.RegionInfo.RegionName);
139
140 if (Directory.Exists(Path.Combine(VIEWER_SUPPORT_DIR, "Floaters")))
141 {
142 OSDMap floaters = new OSDMap();
143 uint n = 0;
144 foreach (String name in Directory.GetFiles(Path.Combine(VIEWER_SUPPORT_DIR, "Floaters"), "*.xml"))
145 {
146 using (StreamReader s = new StreamReader(name))
147 {
148 string simple_name = Path.GetFileNameWithoutExtension(name);
149 OSDMap floater = new OSDMap();
150 floaters[simple_name] = OSDMap.FromString(s.ReadToEnd());
151 n++;
152 }
153 }
154 specialUI["floaters"] = floaters;
155 m_log.DebugFormat("[SPECIAL UI]: Sending {0} floaters", n);
156 }
157 }
158 else
159 m_log.DebugFormat("[SPECIAL UI]: NOT Sending panel_toolbar.xml in {0}", m_scene.RegionInfo.RegionName);
160
161 }
162
163 }
164
165}
diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
index 1d35c54..ceb3332 100644
--- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
+++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
@@ -76,6 +76,10 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
76 /// AutoBackupBusyCheck: True/False. Default: True. 76 /// AutoBackupBusyCheck: True/False. Default: True.
77 /// If True, we will only take an auto-backup if a set of conditions are met. 77 /// If True, we will only take an auto-backup if a set of conditions are met.
78 /// These conditions are heuristics to try and avoid taking a backup when the sim is busy. 78 /// These conditions are heuristics to try and avoid taking a backup when the sim is busy.
79 /// AutoBackupSkipAssets
80 /// If true, assets are not saved to the oar file. Considerably reduces impact on simulator when backing up. Intended for when assets db is backed up separately
81 /// AutoBackupKeepFilesForDays
82 /// Backup files older than this value (in days) are deleted during the current backup process, 0 will disable this and keep all backup files indefinitely
79 /// AutoBackupScript: String. Default: not specified (disabled). 83 /// AutoBackupScript: String. Default: not specified (disabled).
80 /// File path to an executable script or binary to run when an automatic backup is taken. 84 /// File path to an executable script or binary to run when an automatic backup is taken.
81 /// The file should really be (Windows) an .exe or .bat, or (Linux/Mac) a shell script or binary. 85 /// The file should really be (Windows) an .exe or .bat, or (Linux/Mac) a shell script or binary.
@@ -111,6 +115,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
111 115
112 private delegate T DefaultGetter<T>(string settingName, T defaultValue); 116 private delegate T DefaultGetter<T>(string settingName, T defaultValue);
113 private bool m_enabled; 117 private bool m_enabled;
118 private ICommandConsole m_console;
119 private List<Scene> m_Scenes = new List<Scene> ();
120
114 121
115 /// <summary> 122 /// <summary>
116 /// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState! 123 /// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState!
@@ -202,8 +209,20 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
202 /// Currently a no-op for AutoBackup because we have to wait for region to be fully loaded. 209 /// Currently a no-op for AutoBackup because we have to wait for region to be fully loaded.
203 /// </summary> 210 /// </summary>
204 /// <param name="scene"></param> 211 /// <param name="scene"></param>
205 void IRegionModuleBase.AddRegion(Scene scene) 212 void IRegionModuleBase.AddRegion (Scene scene)
206 { 213 {
214 if (!this.m_enabled) {
215 return;
216 }
217 lock (m_Scenes) {
218 m_Scenes.Add (scene);
219 }
220 m_console = MainConsole.Instance;
221
222 m_console.Commands.AddCommand (
223 "AutoBackup", false, "dobackup",
224 "dobackup",
225 "do backup.", DoBackup);
207 } 226 }
208 227
209 /// <summary> 228 /// <summary>
@@ -216,7 +235,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
216 { 235 {
217 return; 236 return;
218 } 237 }
219 238 m_Scenes.Remove (scene);
220 if (this.m_states.ContainsKey(scene)) 239 if (this.m_states.ContainsKey(scene))
221 { 240 {
222 AutoBackupModuleState abms = this.m_states[scene]; 241 AutoBackupModuleState abms = this.m_states[scene];
@@ -258,6 +277,8 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
258 AutoBackupModuleState abms = this.ParseConfig(scene, false); 277 AutoBackupModuleState abms = this.ParseConfig(scene, false);
259 m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName); 278 m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName);
260 m_log.Debug((abms == null ? "DEFAULT" : abms.ToString())); 279 m_log.Debug((abms == null ? "DEFAULT" : abms.ToString()));
280
281 m_states.Add(scene, abms);
261 } 282 }
262 283
263 /// <summary> 284 /// <summary>
@@ -269,6 +290,28 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
269 290
270 #endregion 291 #endregion
271 292
293 private void DoBackup (string module, string[] args)
294 {
295 if (args.Length != 2) {
296 MainConsole.Instance.OutputFormat ("Usage: dobackup <regionname>");
297 return;
298 }
299 bool found = false;
300 string name = args [1];
301 lock (m_Scenes) {
302 foreach (Scene s in m_Scenes) {
303 string test = s.Name.ToString ();
304 if (test == name) {
305 found = true;
306 DoRegionBackup (s);
307 }
308 }
309 if (!found) {
310 MainConsole.Instance.OutputFormat ("No such region {0}. Nothing to backup", name);
311 }
312 }
313 }
314
272 /// <summary> 315 /// <summary>
273 /// Set up internal state for a given scene. Fairly complex code. 316 /// Set up internal state for a given scene. Fairly complex code.
274 /// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene. 317 /// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene.
@@ -334,7 +377,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
334 double interval = 377 double interval =
335 this.ResolveDouble("AutoBackupInterval", this.m_defaultState.IntervalMinutes, 378 this.ResolveDouble("AutoBackupInterval", this.m_defaultState.IntervalMinutes,
336 config, regionConfig) * 60000.0; 379 config, regionConfig) * 60000.0;
337 if (state == null && interval != this.m_defaultState.IntervalMinutes*60000.0) 380 if (state == null && interval != this.m_defaultState.IntervalMinutes * 60000.0)
338 { 381 {
339 state = new AutoBackupModuleState(); 382 state = new AutoBackupModuleState();
340 } 383 }
@@ -412,6 +455,32 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
412 state.BusyCheck = tmpBusyCheck; 455 state.BusyCheck = tmpBusyCheck;
413 } 456 }
414 457
458 // Included Option To Skip Assets
459 bool tmpSkipAssets = ResolveBoolean("AutoBackupSkipAssets",
460 this.m_defaultState.SkipAssets, config, regionConfig);
461 if (state == null && tmpSkipAssets != this.m_defaultState.SkipAssets)
462 {
463 state = new AutoBackupModuleState();
464 }
465
466 if (state != null)
467 {
468 state.SkipAssets = tmpSkipAssets;
469 }
470
471 // How long to keep backup files in days, 0 Disables this feature
472 int tmpKeepFilesForDays = ResolveInt("AutoBackupKeepFilesForDays",
473 this.m_defaultState.KeepFilesForDays, config, regionConfig);
474 if (state == null && tmpKeepFilesForDays != this.m_defaultState.KeepFilesForDays)
475 {
476 state = new AutoBackupModuleState();
477 }
478
479 if (state != null)
480 {
481 state.KeepFilesForDays = tmpKeepFilesForDays;
482 }
483
415 // Set file naming algorithm 484 // Set file naming algorithm
416 string stmpNamingType = ResolveString("AutoBackupNaming", 485 string stmpNamingType = ResolveString("AutoBackupNaming",
417 this.m_defaultState.NamingType.ToString(), config, regionConfig); 486 this.m_defaultState.NamingType.ToString(), config, regionConfig);
@@ -480,7 +549,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
480 catch (Exception e) 549 catch (Exception e)
481 { 550 {
482 m_log.Warn( 551 m_log.Warn(
483 "BAD NEWS. You won't be able to save backups to directory " + 552 "[AUTO BACKUP]: BAD NEWS. You won't be able to save backups to directory " +
484 state.BackupDir + 553 state.BackupDir +
485 " because it doesn't exist or there's a permissions issue with it. Here's the exception.", 554 " because it doesn't exist or there's a permissions issue with it. Here's the exception.",
486 e); 555 e);
@@ -488,6 +557,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
488 } 557 }
489 } 558 }
490 559
560 if(state == null)
561 return m_defaultState;
562
491 return state; 563 return state;
492 } 564 }
493 565
@@ -594,7 +666,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
594 bool heuristicsPassed = false; 666 bool heuristicsPassed = false;
595 if (!this.m_timerMap.ContainsKey((Timer) sender)) 667 if (!this.m_timerMap.ContainsKey((Timer) sender))
596 { 668 {
597 m_log.Debug("Code-up error: timerMap doesn't contain timer " + sender); 669 m_log.Debug("[AUTO BACKUP]: Code-up error: timerMap doesn't contain timer " + sender);
598 } 670 }
599 671
600 List<IScene> tmap = this.m_timerMap[(Timer) sender]; 672 List<IScene> tmap = this.m_timerMap[(Timer) sender];
@@ -630,6 +702,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
630 } 702 }
631 this.DoRegionBackup(scene); 703 this.DoRegionBackup(scene);
632 } 704 }
705
706 // Remove Old Backups
707 this.RemoveOldFiles(state);
633 } 708 }
634 } 709 }
635 } 710 }
@@ -640,7 +715,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
640 /// <param name="scene"></param> 715 /// <param name="scene"></param>
641 private void DoRegionBackup(IScene scene) 716 private void DoRegionBackup(IScene scene)
642 { 717 {
643 if (scene.RegionStatus != RegionStatus.Up) 718 if (!scene.Ready)
644 { 719 {
645 // We won't backup a region that isn't operating normally. 720 // We won't backup a region that isn't operating normally.
646 m_log.Warn("[AUTO BACKUP]: Not backing up region " + scene.RegionInfo.RegionName + 721 m_log.Warn("[AUTO BACKUP]: Not backing up region " + scene.RegionInfo.RegionName +
@@ -662,7 +737,41 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
662 m_pendingSaves.Add(guid, scene); 737 m_pendingSaves.Add(guid, scene);
663 state.LiveRequests.Add(guid, savePath); 738 state.LiveRequests.Add(guid, savePath);
664 ((Scene) scene).EventManager.OnOarFileSaved += new EventManager.OarFileSaved(EventManager_OnOarFileSaved); 739 ((Scene) scene).EventManager.OnOarFileSaved += new EventManager.OarFileSaved(EventManager_OnOarFileSaved);
665 iram.ArchiveRegion(savePath, guid, null); 740
741 m_log.Info("[AUTO BACKUP]: Backing up region " + scene.RegionInfo.RegionName);
742
743 // Must pass options, even if dictionary is empty!
744 Dictionary<string, object> options = new Dictionary<string, object>();
745
746 if (state.SkipAssets)
747 options["noassets"] = true;
748
749 iram.ArchiveRegion(savePath, guid, options);
750 }
751
752 // For the given state, remove backup files older than the states KeepFilesForDays property
753 private void RemoveOldFiles(AutoBackupModuleState state)
754 {
755 // 0 Means Disabled, Keep Files Indefinitely
756 if (state.KeepFilesForDays > 0)
757 {
758 string[] files = Directory.GetFiles(state.BackupDir, "*.oar");
759 DateTime CuttOffDate = DateTime.Now.AddDays(0 - state.KeepFilesForDays);
760
761 foreach (string file in files)
762 {
763 try
764 {
765 FileInfo fi = new FileInfo(file);
766 if (fi.CreationTime < CuttOffDate)
767 fi.Delete();
768 }
769 catch (Exception Ex)
770 {
771 m_log.Error("[AUTO BACKUP]: Error deleting old backup file '" + file + "': " + Ex.Message);
772 }
773 }
774 }
666 } 775 }
667 776
668 /// <summary> 777 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs
index f9e118b..ce7c368 100644
--- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs
+++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs
@@ -45,9 +45,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
45 this.Enabled = false; 45 this.Enabled = false;
46 this.BackupDir = "."; 46 this.BackupDir = ".";
47 this.BusyCheck = true; 47 this.BusyCheck = true;
48 this.SkipAssets = false;
48 this.Timer = null; 49 this.Timer = null;
49 this.NamingType = NamingType.Time; 50 this.NamingType = NamingType.Time;
50 this.Script = null; 51 this.Script = null;
52 this.KeepFilesForDays = 0;
51 } 53 }
52 54
53 public Dictionary<Guid, string> LiveRequests 55 public Dictionary<Guid, string> LiveRequests
@@ -91,6 +93,12 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
91 set; 93 set;
92 } 94 }
93 95
96 public bool SkipAssets
97 {
98 get;
99 set;
100 }
101
94 public string Script 102 public string Script
95 { 103 {
96 get; 104 get;
@@ -109,6 +117,12 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
109 set; 117 set;
110 } 118 }
111 119
120 public int KeepFilesForDays
121 {
122 get;
123 set;
124 }
125
112 public new string ToString() 126 public new string ToString()
113 { 127 {
114 string retval = ""; 128 string retval = "";
diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
index a999b7f..4cd5676 100644
--- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
+++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
@@ -103,7 +103,9 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
103 103
104 #region IMoneyModule Members 104 #region IMoneyModule Members
105 105
106#pragma warning disable 0067
106 public event ObjectPaid OnObjectPaid; 107 public event ObjectPaid OnObjectPaid;
108#pragma warning restore 0067
107 109
108 public int UploadCharge 110 public int UploadCharge
109 { 111 {
@@ -191,9 +193,14 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
191 // Please do not refactor these to be just one method 193 // Please do not refactor these to be just one method
192 // Existing implementations need the distinction 194 // Existing implementations need the distinction
193 // 195 //
194 public void ApplyCharge(UUID agentID, int amount, string text) 196 public void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData)
195 { 197 {
196 } 198 }
199
200 public void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type)
201 {
202 }
203
197 public void ApplyUploadCharge(UUID agentID, int amount, string text) 204 public void ApplyUploadCharge(UUID agentID, int amount, string text)
198 { 205 {
199 } 206 }
@@ -322,7 +329,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
322 client.SendAlertMessage(e.Message + " "); 329 client.SendAlertMessage(e.Message + " ");
323 } 330 }
324 331
325 client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds); 332 client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds, 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
326 } 333 }
327 else 334 else
328 { 335 {
@@ -385,12 +392,12 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
385 { 392 {
386 if (sender != null) 393 if (sender != null)
387 { 394 {
388 sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(senderID)); 395 sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(senderID), 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
389 } 396 }
390 397
391 if (receiver != null) 398 if (receiver != null)
392 { 399 {
393 receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(receiverID)); 400 receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(receiverID), 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
394 } 401 }
395 } 402 }
396 } 403 }
@@ -555,7 +562,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
555 /// <returns></returns> 562 /// <returns></returns>
556 private int GetFundsForAgentID(UUID AgentID) 563 private int GetFundsForAgentID(UUID AgentID)
557 { 564 {
558 int returnfunds = 75004; // Set it to the OpenSim version, plus the IG build number. Muahahaha; 565 int returnfunds = 0;
559 566
560 return returnfunds; 567 return returnfunds;
561 } 568 }
@@ -688,19 +695,14 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
688 /// Event called Economy Data Request handler. 695 /// Event called Economy Data Request handler.
689 /// </summary> 696 /// </summary>
690 /// <param name="agentId"></param> 697 /// <param name="agentId"></param>
691 public void EconomyDataRequestHandler(UUID agentId) 698 public void EconomyDataRequestHandler(IClientAPI user)
692 { 699 {
693 IClientAPI user = LocateClientObject(agentId); 700 Scene s = (Scene)user.Scene;
694 701
695 if (user != null) 702 user.SendEconomyData(EnergyEfficiency, s.RegionInfo.ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate,
696 { 703 PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor,
697 Scene s = LocateSceneClientIn(user.AgentId); 704 PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload,
698 705 TeleportMinPrice, TeleportPriceExponent);
699 user.SendEconomyData(EnergyEfficiency, s.RegionInfo.ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate,
700 PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor,
701 PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload,
702 TeleportMinPrice, TeleportPriceExponent);
703 }
704 } 706 }
705 707
706 private void ValidateLandBuy(Object osender, EventManager.LandBuyArgs e) 708 private void ValidateLandBuy(Object osender, EventManager.LandBuyArgs e)
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 5ea2bcd..fb644b7 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -44,10 +44,24 @@ namespace OpenSim.Region.OptionalModules.World.NPC
44 { 44 {
45 public bool SenseAsAgent { get; set; } 45 public bool SenseAsAgent { get; set; }
46 46
47 public delegate void ChatToNPC(
48 string message, byte type, Vector3 fromPos, string fromName,
49 UUID fromAgentID, UUID ownerID, byte source, byte audible);
50
51 /// <summary>
52 /// Fired when the NPC receives a chat message.
53 /// </summary>
54 public event ChatToNPC OnChatToNPC;
55
56 /// <summary>
57 /// Fired when the NPC receives an instant message.
58 /// </summary>
59 public event Action<GridInstantMessage> OnInstantMessageToNPC;
60
47 private readonly string m_firstname; 61 private readonly string m_firstname;
48 private readonly string m_lastname; 62 private readonly string m_lastname;
49 private readonly Vector3 m_startPos; 63 private readonly Vector3 m_startPos;
50 private readonly UUID m_uuid = UUID.Random(); 64 private readonly UUID m_uuid;
51 private readonly Scene m_scene; 65 private readonly Scene m_scene;
52 private readonly UUID m_ownerID; 66 private readonly UUID m_ownerID;
53 67
@@ -57,6 +71,19 @@ namespace OpenSim.Region.OptionalModules.World.NPC
57 m_firstname = firstname; 71 m_firstname = firstname;
58 m_lastname = lastname; 72 m_lastname = lastname;
59 m_startPos = position; 73 m_startPos = position;
74 m_uuid = UUID.Random();
75 m_scene = scene;
76 m_ownerID = ownerID;
77 SenseAsAgent = senseAsAgent;
78 }
79
80 public NPCAvatar(
81 string firstname, string lastname, UUID agentID, Vector3 position, UUID ownerID, bool senseAsAgent, Scene scene)
82 {
83 m_firstname = firstname;
84 m_lastname = lastname;
85 m_startPos = position;
86 m_uuid = agentID;
60 m_scene = scene; 87 m_scene = scene;
61 m_ownerID = ownerID; 88 m_ownerID = ownerID;
62 SenseAsAgent = senseAsAgent; 89 SenseAsAgent = senseAsAgent;
@@ -258,6 +285,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
258 public event Action<IClientAPI, bool> OnCompleteMovementToRegion; 285 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
259 public event UpdateAgent OnPreAgentUpdate; 286 public event UpdateAgent OnPreAgentUpdate;
260 public event UpdateAgent OnAgentUpdate; 287 public event UpdateAgent OnAgentUpdate;
288 public event UpdateAgent OnAgentCameraUpdate;
261 public event AgentRequestSit OnAgentRequestSit; 289 public event AgentRequestSit OnAgentRequestSit;
262 public event AgentSit OnAgentSit; 290 public event AgentSit OnAgentSit;
263 public event AvatarPickerRequest OnAvatarPickerRequest; 291 public event AvatarPickerRequest OnAvatarPickerRequest;
@@ -391,6 +419,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
391 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest; 419 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
392 public event EstateChangeInfo OnEstateChangeInfo; 420 public event EstateChangeInfo OnEstateChangeInfo;
393 public event EstateManageTelehub OnEstateManageTelehub; 421 public event EstateManageTelehub OnEstateManageTelehub;
422 public event CachedTextureRequest OnCachedTextureRequest;
394 public event ScriptReset OnScriptReset; 423 public event ScriptReset OnScriptReset;
395 public event GetScriptRunning OnGetScriptRunning; 424 public event GetScriptRunning OnGetScriptRunning;
396 public event SetScriptRunning OnSetScriptRunning; 425 public event SetScriptRunning OnSetScriptRunning;
@@ -569,6 +598,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
569 { 598 {
570 } 599 }
571 600
601 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
602 {
603
604 }
605
572 public virtual void Kick(string message) 606 public virtual void Kick(string message)
573 { 607 {
574 } 608 }
@@ -586,7 +620,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
586 620
587 } 621 }
588 622
589 public virtual void SendKillObject(ulong regionHandle, List<uint> localID) 623 public virtual void SendKillObject(List<uint> localID)
590 { 624 {
591 } 625 }
592 626
@@ -607,25 +641,26 @@ namespace OpenSim.Region.OptionalModules.World.NPC
607 string message, byte type, Vector3 fromPos, string fromName, 641 string message, byte type, Vector3 fromPos, string fromName,
608 UUID fromAgentID, UUID ownerID, byte source, byte audible) 642 UUID fromAgentID, UUID ownerID, byte source, byte audible)
609 { 643 {
610 } 644 ChatToNPC ctn = OnChatToNPC;
611 645
612 public virtual void SendChatMessage( 646 if (ctn != null)
613 byte[] message, byte type, Vector3 fromPos, string fromName, 647 ctn(message, type, fromPos, fromName, fromAgentID, ownerID, source, audible);
614 UUID fromAgentID, UUID ownerID, byte source, byte audible)
615 {
616 } 648 }
617 649
618 public void SendInstantMessage(GridInstantMessage im) 650 public void SendInstantMessage(GridInstantMessage im)
619 { 651 {
620 652 Action<GridInstantMessage> oimtn = OnInstantMessageToNPC;
653
654 if (oimtn != null)
655 oimtn(im);
621 } 656 }
622 657
623 public void SendGenericMessage(string method, List<string> message) 658 public void SendGenericMessage(string method, UUID invoice, List<string> message)
624 { 659 {
625 660
626 } 661 }
627 662
628 public void SendGenericMessage(string method, List<byte[]> message) 663 public void SendGenericMessage(string method, UUID invoice, List<byte[]> message)
629 { 664 {
630 665
631 } 666 }
@@ -688,7 +723,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
688 { 723 {
689 } 724 }
690 725
691 public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) 726 public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item)
692 { 727 {
693 } 728 }
694 729
@@ -860,11 +895,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
860 { 895 {
861 } 896 }
862 897
863 public bool AddMoney(int debit)
864 {
865 return false;
866 }
867
868 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase) 898 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase)
869 { 899 {
870 } 900 }
@@ -1227,12 +1257,17 @@ namespace OpenSim.Region.OptionalModules.World.NPC
1227 { 1257 {
1228 } 1258 }
1229 1259
1230 public void StopFlying(ISceneEntity presence) 1260 public void SendAgentTerseUpdate(ISceneEntity presence)
1231 { 1261 {
1232 } 1262 }
1233 1263
1234 public void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data) 1264 public void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data)
1235 { 1265 {
1236 } 1266 }
1267
1268 public void SendPartPhysicsProprieties(ISceneEntity entity)
1269 {
1270 }
1271
1237 } 1272 }
1238} 1273}
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index d6cf1ab..9232db9 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -116,7 +116,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
116 return false; 116 return false;
117 117
118 // Delete existing npc attachments 118 // Delete existing npc attachments
119 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false); 119 if(scene.AttachmentsModule != null)
120 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false);
120 121
121 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet 122 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet
122 // since it doesn't transfer attachments 123 // since it doesn't transfer attachments
@@ -125,7 +126,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
125 npc.Appearance = npcAppearance; 126 npc.Appearance = npcAppearance;
126 127
127 // Rez needed npc attachments 128 // Rez needed npc attachments
128 scene.AttachmentsModule.RezAttachments(npc); 129 if (scene.AttachmentsModule != null)
130 scene.AttachmentsModule.RezAttachments(npc);
129 131
130 IAvatarFactoryModule module = 132 IAvatarFactoryModule module =
131 scene.RequestModuleInterface<IAvatarFactoryModule>(); 133 scene.RequestModuleInterface<IAvatarFactoryModule>();
@@ -138,15 +140,37 @@ namespace OpenSim.Region.OptionalModules.World.NPC
138 Vector3 position, UUID owner, bool senseAsAgent, Scene scene, 140 Vector3 position, UUID owner, bool senseAsAgent, Scene scene,
139 AvatarAppearance appearance) 141 AvatarAppearance appearance)
140 { 142 {
141 NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, 143 return CreateNPC(firstname, lastname, position, UUID.Zero, owner, senseAsAgent, scene, appearance);
142 owner, senseAsAgent, scene); 144 }
145
146 public UUID CreateNPC(string firstname, string lastname,
147 Vector3 position, UUID agentID, UUID owner, bool senseAsAgent, Scene scene,
148 AvatarAppearance appearance)
149 {
150 NPCAvatar npcAvatar = null;
151
152 try
153 {
154 if (agentID == UUID.Zero)
155 npcAvatar = new NPCAvatar(firstname, lastname, position,
156 owner, senseAsAgent, scene);
157 else
158 npcAvatar = new NPCAvatar(firstname, lastname, agentID, position,
159 owner, senseAsAgent, scene);
160 }
161 catch (Exception e)
162 {
163 m_log.Info("[NPC MODULE]: exception creating NPC avatar: " + e.ToString());
164 return UUID.Zero;
165 }
166
143 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, 167 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0,
144 int.MaxValue); 168 int.MaxValue);
145 169
146 m_log.DebugFormat( 170 m_log.DebugFormat(
147 "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}", 171 "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}",
148 firstname, lastname, npcAvatar.AgentId, owner, 172 firstname, lastname, npcAvatar.AgentId, owner,
149 senseAsAgent, position, scene.RegionInfo.RegionName); 173 senseAsAgent, position, scene.RegionInfo.RegionName);
150 174
151 AgentCircuitData acd = new AgentCircuitData(); 175 AgentCircuitData acd = new AgentCircuitData();
152 acd.AgentID = npcAvatar.AgentId; 176 acd.AgentID = npcAvatar.AgentId;
@@ -154,8 +178,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
154 acd.lastname = lastname; 178 acd.lastname = lastname;
155 acd.ServiceURLs = new Dictionary<string, object>(); 179 acd.ServiceURLs = new Dictionary<string, object>();
156 180
157 AvatarAppearance npcAppearance = new AvatarAppearance(appearance, 181 AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true);
158 true);
159 acd.Appearance = npcAppearance; 182 acd.Appearance = npcAppearance;
160 183
161 /* 184 /*
@@ -173,7 +196,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
173 { 196 {
174 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, 197 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode,
175 acd); 198 acd);
176 scene.AddNewClient(npcAvatar, PresenceType.Npc); 199 scene.AddNewAgent(npcAvatar, PresenceType.Npc);
177 200
178 ScenePresence sp; 201 ScenePresence sp;
179 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) 202 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
@@ -186,16 +209,16 @@ namespace OpenSim.Region.OptionalModules.World.NPC
186 209
187 sp.CompleteMovement(npcAvatar, false); 210 sp.CompleteMovement(npcAvatar, false);
188 m_avatars.Add(npcAvatar.AgentId, npcAvatar); 211 m_avatars.Add(npcAvatar.AgentId, npcAvatar);
189 m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", 212 m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
190 npcAvatar.AgentId, sp.Name);
191 213
192 return npcAvatar.AgentId; 214 return npcAvatar.AgentId;
193 } 215 }
194 else 216 else
195 { 217 {
196 m_log.WarnFormat( 218 m_log.WarnFormat(
197 "[NPC MODULE]: Could not find scene presence for NPC {0} {1}", 219 "[NPC MODULE]: Could not find scene presence for NPC {0} {1}",
198 sp.Name, sp.UUID); 220 sp.Name, sp.UUID);
221
199 return UUID.Zero; 222 return UUID.Zero;
200 } 223 }
201 } 224 }
@@ -211,12 +234,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
211 ScenePresence sp; 234 ScenePresence sp;
212 if (scene.TryGetScenePresence(agentID, out sp)) 235 if (scene.TryGetScenePresence(agentID, out sp))
213 { 236 {
214 /* 237 if (sp.IsSatOnObject || sp.SitGround)
215 m_log.DebugFormat( 238 return false;
216 "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}", 239
217 sp.Name, pos, scene.RegionInfo.RegionName, 240// m_log.DebugFormat(
218 noFly, landAtTarget); 241// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
219 */ 242// sp.Name, pos, scene.RegionInfo.RegionName,
243// noFly, landAtTarget);
220 244
221 sp.MoveToTarget(pos, noFly, landAtTarget); 245 sp.MoveToTarget(pos, noFly, landAtTarget);
222 sp.SetAlwaysRun = running; 246 sp.SetAlwaysRun = running;
@@ -293,9 +317,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
293 ScenePresence sp; 317 ScenePresence sp;
294 if (scene.TryGetScenePresence(agentID, out sp)) 318 if (scene.TryGetScenePresence(agentID, out sp))
295 { 319 {
296 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, 320 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
297 partID, Vector3.Zero);
298 //sp.HandleAgentSit(m_avatars[agentID], agentID);
299 321
300 return true; 322 return true;
301 } 323 }
@@ -376,23 +398,30 @@ namespace OpenSim.Region.OptionalModules.World.NPC
376 398
377 public bool DeleteNPC(UUID agentID, Scene scene) 399 public bool DeleteNPC(UUID agentID, Scene scene)
378 { 400 {
401 bool doRemove = false;
402 NPCAvatar av;
379 lock (m_avatars) 403 lock (m_avatars)
380 { 404 {
381 NPCAvatar av;
382 if (m_avatars.TryGetValue(agentID, out av)) 405 if (m_avatars.TryGetValue(agentID, out av))
383 { 406 {
384 /* 407 /*
385 m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove", 408 m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove",
386 agentID, av.Name); 409 agentID, av.Name);
387 */ 410 */
388 scene.RemoveClient(agentID, false); 411 doRemove = true;
412 }
413 }
414
415 if (doRemove)
416 {
417 scene.CloseAgent(agentID, false);
418 lock (m_avatars)
419 {
389 m_avatars.Remove(agentID); 420 m_avatars.Remove(agentID);
390 /*
391 m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}",
392 agentID, av.Name);
393 */
394 return true;
395 } 421 }
422 m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}",
423 agentID, av.Name);
424 return true;
396 } 425 }
397 /* 426 /*
398 m_log.DebugFormat("[NPC MODULE]: Could not find {0} to remove", 427 m_log.DebugFormat("[NPC MODULE]: Could not find {0} to remove",
@@ -416,13 +445,20 @@ namespace OpenSim.Region.OptionalModules.World.NPC
416 /// <summary> 445 /// <summary>
417 /// Check if the caller has permission to manipulate the given NPC. 446 /// Check if the caller has permission to manipulate the given NPC.
418 /// </summary> 447 /// </summary>
448 /// <remarks>
449 /// A caller has permission if
450 /// * The caller UUID given is UUID.Zero.
451 /// * The avatar is unowned (owner is UUID.Zero).
452 /// * The avatar is owned and the owner and callerID match.
453 /// * The avatar is owned and the callerID matches its agentID.
454 /// </remarks>
419 /// <param name="av"></param> 455 /// <param name="av"></param>
420 /// <param name="callerID"></param> 456 /// <param name="callerID"></param>
421 /// <returns>true if they do, false if they don't.</returns> 457 /// <returns>true if they do, false if they don't.</returns>
422 private bool CheckPermissions(NPCAvatar av, UUID callerID) 458 private bool CheckPermissions(NPCAvatar av, UUID callerID)
423 { 459 {
424 return callerID == UUID.Zero || av.OwnerID == UUID.Zero || 460 return callerID == UUID.Zero || av.OwnerID == UUID.Zero ||
425 av.OwnerID == callerID; 461 av.OwnerID == callerID || av.AgentId == callerID;
426 } 462 }
427 } 463 }
428} 464}
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index bf23040..77dfd40 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -33,7 +33,6 @@ using Nini.Config;
33using NUnit.Framework; 33using NUnit.Framework;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Communications;
37using OpenSim.Region.CoreModules.Avatar.Attachments; 36using OpenSim.Region.CoreModules.Avatar.Attachments;
38using OpenSim.Region.CoreModules.Avatar.AvatarFactory; 37using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
39using OpenSim.Region.CoreModules.Framework.InventoryAccess; 38using OpenSim.Region.CoreModules.Framework.InventoryAccess;
@@ -43,7 +42,6 @@ using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
44using OpenSim.Services.AvatarService; 43using OpenSim.Services.AvatarService;
45using OpenSim.Tests.Common; 44using OpenSim.Tests.Common;
46using OpenSim.Tests.Common.Mock;
47 45
48namespace OpenSim.Region.OptionalModules.World.NPC.Tests 46namespace OpenSim.Region.OptionalModules.World.NPC.Tests
49{ 47{
@@ -71,11 +69,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
71 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; 69 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
72 } 70 }
73 71
74 [SetUp] 72 public void SetUpScene()
75 public void Init()
76 { 73 {
77 base.SetUp(); 74 SetUpScene(256, 256);
75 }
78 76
77 public void SetUpScene(uint sizeX, uint sizeY)
78 {
79 IConfigSource config = new IniConfigSource(); 79 IConfigSource config = new IniConfigSource();
80 config.AddConfig("NPC"); 80 config.AddConfig("NPC");
81 config.Configs["NPC"].Set("Enabled", "true"); 81 config.Configs["NPC"].Set("Enabled", "true");
@@ -87,7 +87,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
87 m_attMod = new AttachmentsModule(); 87 m_attMod = new AttachmentsModule();
88 m_npcMod = new NPCModule(); 88 m_npcMod = new NPCModule();
89 89
90 m_scene = new SceneHelpers().SetupScene(); 90 m_scene = new SceneHelpers().SetupScene("test scene", UUID.Random(), 1000, 1000, sizeX, sizeY, config);
91 SceneHelpers.SetupSceneModules(m_scene, config, m_afMod, m_umMod, m_attMod, m_npcMod, new BasicInventoryAccessModule()); 91 SceneHelpers.SetupSceneModules(m_scene, config, m_afMod, m_umMod, m_attMod, m_npcMod, new BasicInventoryAccessModule());
92 } 92 }
93 93
@@ -97,6 +97,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
97 TestHelpers.InMethod(); 97 TestHelpers.InMethod();
98// log4net.Config.XmlConfigurator.Configure(); 98// log4net.Config.XmlConfigurator.Configure();
99 99
100 SetUpScene();
101
100 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); 102 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
101// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); 103// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId);
102 104
@@ -110,7 +112,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
110 // ScenePresence.SendInitialData() to reset our entire appearance. 112 // ScenePresence.SendInitialData() to reset our entire appearance.
111 m_scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); 113 m_scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId));
112 114
113 m_afMod.SetAppearance(sp, originalTe, null); 115 m_afMod.SetAppearance(sp, originalTe, null, null);
114 116
115 UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance); 117 UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance);
116 118
@@ -133,6 +135,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
133 TestHelpers.InMethod(); 135 TestHelpers.InMethod();
134// log4net.Config.XmlConfigurator.Configure(); 136// log4net.Config.XmlConfigurator.Configure();
135 137
138 SetUpScene();
139
136 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); 140 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
137// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); 141// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId);
138 142
@@ -155,7 +159,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
155 public void TestCreateWithAttachments() 159 public void TestCreateWithAttachments()
156 { 160 {
157 TestHelpers.InMethod(); 161 TestHelpers.InMethod();
158// log4net.Config.XmlConfigurator.Configure(); 162// TestHelpers.EnableLogging();
163
164 SetUpScene();
159 165
160 UUID userId = TestHelpers.ParseTail(0x1); 166 UUID userId = TestHelpers.ParseTail(0x1);
161 UserAccountHelpers.CreateUserWithInventory(m_scene, userId); 167 UserAccountHelpers.CreateUserWithInventory(m_scene, userId);
@@ -191,11 +197,66 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
191 } 197 }
192 198
193 [Test] 199 [Test]
200 public void TestCreateWithMultiAttachments()
201 {
202 TestHelpers.InMethod();
203// TestHelpers.EnableLogging();
204
205 SetUpScene();
206// m_attMod.DebugLevel = 1;
207
208 UUID userId = TestHelpers.ParseTail(0x1);
209 UserAccountHelpers.CreateUserWithInventory(m_scene, userId);
210 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
211
212 InventoryItemBase att1Item
213 = UserInventoryHelpers.CreateInventoryItem(
214 m_scene, "att1", TestHelpers.ParseTail(0x2), TestHelpers.ParseTail(0x3), sp.UUID, InventoryType.Object);
215 InventoryItemBase att2Item
216 = UserInventoryHelpers.CreateInventoryItem(
217 m_scene, "att2", TestHelpers.ParseTail(0x12), TestHelpers.ParseTail(0x13), sp.UUID, InventoryType.Object);
218
219 m_attMod.RezSingleAttachmentFromInventory(sp, att1Item.ID, (uint)AttachmentPoint.Chest);
220 m_attMod.RezSingleAttachmentFromInventory(sp, att2Item.ID, (uint)AttachmentPoint.Chest | 0x80);
221
222 UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance);
223
224 ScenePresence npc = m_scene.GetScenePresence(npcId);
225
226 // Check scene presence status
227 Assert.That(npc.HasAttachments(), Is.True);
228 List<SceneObjectGroup> attachments = npc.GetAttachments();
229 Assert.That(attachments.Count, Is.EqualTo(2));
230
231 // Just for now, we won't test the name since this is (wrongly) the asset part name rather than the item
232 // name. TODO: Do need to fix ultimately since the item may be renamed before being passed on to an NPC.
233// Assert.That(attSo.Name, Is.EqualTo(attName));
234
235 TestAttachedObject(attachments[0], AttachmentPoint.Chest, npc.UUID);
236 TestAttachedObject(attachments[1], AttachmentPoint.Chest, npc.UUID);
237
238 // Attached objects on the same point must have different FromItemIDs to be shown to other avatars, at least
239 // on Singularity 1.8.5. Otherwise, only one (the first ObjectUpdate sent) appears.
240 Assert.AreNotEqual(attachments[0].FromItemID, attachments[1].FromItemID);
241 }
242
243 private void TestAttachedObject(SceneObjectGroup attSo, AttachmentPoint attPoint, UUID ownerId)
244 {
245 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)attPoint));
246 Assert.That(attSo.IsAttachment);
247 Assert.That(attSo.UsesPhysics, Is.False);
248 Assert.That(attSo.IsTemporary, Is.False);
249 Assert.That(attSo.OwnerID, Is.EqualTo(ownerId));
250 }
251
252 [Test]
194 public void TestLoadAppearance() 253 public void TestLoadAppearance()
195 { 254 {
196 TestHelpers.InMethod(); 255 TestHelpers.InMethod();
197// log4net.Config.XmlConfigurator.Configure(); 256// log4net.Config.XmlConfigurator.Configure();
198 257
258 SetUpScene();
259
199 UUID userId = TestHelpers.ParseTail(0x1); 260 UUID userId = TestHelpers.ParseTail(0x1);
200 UserAccountHelpers.CreateUserWithInventory(m_scene, userId); 261 UserAccountHelpers.CreateUserWithInventory(m_scene, userId);
201 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); 262 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
@@ -237,7 +298,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
237 public void TestMove() 298 public void TestMove()
238 { 299 {
239 TestHelpers.InMethod(); 300 TestHelpers.InMethod();
240// log4net.Config.XmlConfigurator.Configure(); 301// TestHelpers.EnableLogging();
302
303 SetUpScene();
241 304
242 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); 305 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
243// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); 306// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId);
@@ -303,11 +366,64 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
303 } 366 }
304 367
305 [Test] 368 [Test]
369 public void TestMoveInVarRegion()
370 {
371 TestHelpers.InMethod();
372// TestHelpers.EnableLogging();
373
374 SetUpScene(512, 512);
375
376 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
377// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId);
378
379 Vector3 startPos = new Vector3(128, 246, 30);
380 UUID npcId = m_npcMod.CreateNPC("John", "Smith", startPos, UUID.Zero, true, m_scene, sp.Appearance);
381
382 ScenePresence npc = m_scene.GetScenePresence(npcId);
383 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
384
385 // For now, we'll make the scene presence fly to simplify this test, but this needs to change.
386 npc.Flying = true;
387
388 m_scene.Update(1);
389 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
390
391 Vector3 targetPos = startPos + new Vector3(0, 20, 0);
392 m_npcMod.MoveToTarget(npc.UUID, m_scene, targetPos, false, false, false);
393
394 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
395 //Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0.7071068f, 0.7071068f)));
396 Assert.That(
397 npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001));
398
399 m_scene.Update(1);
400
401 // We should really check the exact figure.
402 Assert.That(npc.AbsolutePosition.X, Is.EqualTo(startPos.X));
403 Assert.That(npc.AbsolutePosition.Y, Is.GreaterThan(startPos.Y));
404 Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
405 Assert.That(npc.AbsolutePosition.Z, Is.LessThan(targetPos.X));
406
407 for (int i = 0; i < 20; i++)
408 {
409 m_scene.Update(1);
410// Console.WriteLine("pos: {0}", npc.AbsolutePosition);
411 }
412
413 double distanceToTarget = Util.GetDistanceTo(npc.AbsolutePosition, targetPos);
414 Assert.That(distanceToTarget, Is.LessThan(1), "NPC not within 1 unit of target position on first move");
415 Assert.That(npc.AbsolutePosition, Is.EqualTo(targetPos));
416 Assert.That(npc.AgentControlFlags, Is.EqualTo((uint)AgentManager.ControlFlags.NONE));
417 }
418
419 [Test]
306 public void TestSitAndStandWithSitTarget() 420 public void TestSitAndStandWithSitTarget()
307 { 421 {
308 TestHelpers.InMethod(); 422 TestHelpers.InMethod();
309// log4net.Config.XmlConfigurator.Configure(); 423// log4net.Config.XmlConfigurator.Configure();
310 424
425 SetUpScene();
426
311 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); 427 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
312 428
313 Vector3 startPos = new Vector3(128, 128, 30); 429 Vector3 startPos = new Vector3(128, 128, 30);
@@ -321,9 +437,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
321 437
322 Assert.That(part.SitTargetAvatar, Is.EqualTo(npcId)); 438 Assert.That(part.SitTargetAvatar, Is.EqualTo(npcId));
323 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); 439 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId));
324 Assert.That( 440// Assert.That(
325 npc.AbsolutePosition, 441// npc.AbsolutePosition,
326 Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); 442// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
327 443
328 m_npcMod.Stand(npc.UUID, m_scene); 444 m_npcMod.Stand(npc.UUID, m_scene);
329 445
@@ -335,7 +451,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
335 public void TestSitAndStandWithNoSitTarget() 451 public void TestSitAndStandWithNoSitTarget()
336 { 452 {
337 TestHelpers.InMethod(); 453 TestHelpers.InMethod();
338// log4net.Config.XmlConfigurator.Configure(); 454// TestHelpers.EnableLogging();
455
456 SetUpScene();
339 457
340 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); 458 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
341 459
@@ -353,13 +471,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
353 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); 471 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
354 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); 472 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId));
355 473
356 // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the 474 // We should really be using the NPC size but this would mean preserving the physics actor since it is
357 // default avatar. 475 // removed on sit.
358 // Curiously, Vector3.ToString() will not display the last two places of the float. For example,
359 // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337>
360 Assert.That( 476 Assert.That(
361 npc.AbsolutePosition, 477 npc.AbsolutePosition,
362 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, 0.845499337f))); 478 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, sp.PhysicsActor.Size.Z / 2)));
363 479
364 m_npcMod.Stand(npc.UUID, m_scene); 480 m_npcMod.Stand(npc.UUID, m_scene);
365 481
@@ -367,4 +483,4 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
367 Assert.That(npc.ParentID, Is.EqualTo(0)); 483 Assert.That(npc.ParentID, Is.EqualTo(0));
368 } 484 }
369 } 485 }
370} 486} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
index 12169ab..0927c4f 100644
--- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.Linq; 30using System.Linq;
31using System.Reflection; 31using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Threading;
33using log4net; 34using log4net;
34using Mono.Addins; 35using Mono.Addins;
35using Nini.Config; 36using Nini.Config;
@@ -48,7 +49,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SceneCommandsModule")] 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SceneCommandsModule")]
49 public class SceneCommandsModule : ISceneCommandsModule, INonSharedRegionModule 50 public class SceneCommandsModule : ISceneCommandsModule, INonSharedRegionModule
50 { 51 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 53
53 private Scene m_scene; 54 private Scene m_scene;
54 55
@@ -93,28 +94,44 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
93 "Debug", this, "debug scene get", 94 "Debug", this, "debug scene get",
94 "debug scene get", 95 "debug scene get",
95 "List current scene options.", 96 "List current scene options.",
96 "If active is false then main scene update and maintenance loops are suspended.\n" 97 "active - if false then main scene update and maintenance loops are suspended.\n"
97 + "If animations is true then extra animations debug information is logged.\n" 98 + "animations - if true then extra animations debug information is logged.\n"
98 + "If collisions is false then collisions with other objects are turned off.\n" 99 + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n"
99 + "If pbackup is false then periodic scene backup is turned off.\n" 100 + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n"
100 + "If physics is false then all physics objects are non-physical.\n" 101 + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
101 + "If scripting is false then no scripting operations happen.\n" 102 + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
102 + "If teleport is true then some extra teleport debug information is logged.\n" 103 + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n"
103 + "If updates is true then any frame which exceeds double the maximum desired frame time is logged.", 104 + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n"
105 + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n"
106 + "collisions - if false then collisions with other objects are turned off.\n"
107 + "pbackup - if false then periodic scene backup is turned off.\n"
108 + "physics - if false then all physics objects are non-physical.\n"
109 + "scripting - if false then no scripting operations happen.\n"
110 + "teleport - if true then some extra teleport debug information is logged.\n"
111 + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n"
112 + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.",
104 HandleDebugSceneGetCommand); 113 HandleDebugSceneGetCommand);
105 114
106 scene.AddCommand( 115 scene.AddCommand(
107 "Debug", this, "debug scene set", 116 "Debug", this, "debug scene set",
108 "debug scene set active|collisions|pbackup|physics|scripting|teleport|updates true|false", 117 "debug scene set <param> <value>",
109 "Turn on scene debugging options.", 118 "Turn on scene debugging options.",
110 "If active is false then main scene update and maintenance loops are suspended.\n" 119 "active - if false then main scene update and maintenance loops are suspended.\n"
111 + "If animations is true then extra animations debug information is logged.\n" 120 + "animations - if true then extra animations debug information is logged.\n"
112 + "If collisions is false then collisions with other objects are turned off.\n" 121 + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n"
113 + "If pbackup is false then periodic scene backup is turned off.\n" 122 + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n"
114 + "If physics is false then all physics objects are non-physical.\n" 123 + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
115 + "If scripting is false then no scripting operations happen.\n" 124 + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
116 + "If teleport is true then some extra teleport debug information is logged.\n" 125 + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n"
117 + "If updates is true then any frame which exceeds double the maximum desired frame time is logged.", 126 + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n"
127 + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n"
128 + "collisions - if false then collisions with other objects are turned off.\n"
129 + "pbackup - if false then periodic scene backup is turned off.\n"
130 + "physics - if false then all physics objects are non-physical.\n"
131 + "scripting - if false then no scripting operations happen.\n"
132 + "teleport - if true then some extra teleport debug information is logged.\n"
133 + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n"
134 + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.",
118 HandleDebugSceneSetCommand); 135 HandleDebugSceneSetCommand);
119 } 136 }
120 137
@@ -138,10 +155,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
138 ConsoleDisplayList cdl = new ConsoleDisplayList(); 155 ConsoleDisplayList cdl = new ConsoleDisplayList();
139 cdl.AddRow("active", m_scene.Active); 156 cdl.AddRow("active", m_scene.Active);
140 cdl.AddRow("animations", m_scene.DebugAnimations); 157 cdl.AddRow("animations", m_scene.DebugAnimations);
158 cdl.AddRow("appear-refresh", m_scene.SendPeriodicAppearanceUpdates);
159 cdl.AddRow("child-repri", m_scene.ChildReprioritizationDistance);
160 cdl.AddRow("client-pos-upd", m_scene.RootPositionUpdateTolerance);
161 cdl.AddRow("client-rot-upd", m_scene.RootRotationUpdateTolerance);
162 cdl.AddRow("client-vel-upd", m_scene.RootVelocityUpdateTolerance);
163 cdl.AddRow("root-upd-per", m_scene.RootTerseUpdatePeriod);
164 cdl.AddRow("child-upd-per", m_scene.ChildTerseUpdatePeriod);
141 cdl.AddRow("pbackup", m_scene.PeriodicBackup); 165 cdl.AddRow("pbackup", m_scene.PeriodicBackup);
142 cdl.AddRow("physics", m_scene.PhysicsEnabled); 166 cdl.AddRow("physics", m_scene.PhysicsEnabled);
143 cdl.AddRow("scripting", m_scene.ScriptsEnabled); 167 cdl.AddRow("scripting", m_scene.ScriptsEnabled);
144 cdl.AddRow("teleport", m_scene.DebugTeleporting); 168 cdl.AddRow("teleport", m_scene.DebugTeleporting);
169 cdl.AddRow("update-on-timer", m_scene.UpdateOnTimer);
145 cdl.AddRow("updates", m_scene.DebugUpdates); 170 cdl.AddRow("updates", m_scene.DebugUpdates);
146 171
147 MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name); 172 MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name);
@@ -163,8 +188,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
163 } 188 }
164 else 189 else
165 { 190 {
166 MainConsole.Instance.Output( 191 MainConsole.Instance.Output("Usage: debug scene set <param> <value>");
167 "Usage: debug scene set active|collisions|pbackup|physics|scripting|teleport|updates true|false");
168 } 192 }
169 } 193 }
170 194
@@ -186,6 +210,69 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
186 m_scene.DebugAnimations = active; 210 m_scene.DebugAnimations = active;
187 } 211 }
188 212
213 if (options.ContainsKey("appear-refresh"))
214 {
215 bool newValue;
216
217 // FIXME: This can only come from the console at the moment but might not always be true.
218 if (ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, options["appear-refresh"], out newValue))
219 m_scene.SendPeriodicAppearanceUpdates = newValue;
220 }
221
222 if (options.ContainsKey("child-repri"))
223 {
224 double newValue;
225
226 // FIXME: This can only come from the console at the moment but might not always be true.
227 if (ConsoleUtil.TryParseConsoleDouble(MainConsole.Instance, options["child-repri"], out newValue))
228 m_scene.ChildReprioritizationDistance = newValue;
229 }
230
231 if (options.ContainsKey("client-pos-upd"))
232 {
233 float newValue;
234
235 // FIXME: This can only come from the console at the moment but might not always be true.
236 if (ConsoleUtil.TryParseConsoleFloat(MainConsole.Instance, options["client-pos-upd"], out newValue))
237 m_scene.RootPositionUpdateTolerance = newValue;
238 }
239
240 if (options.ContainsKey("client-rot-upd"))
241 {
242 float newValue;
243
244 // FIXME: This can only come from the console at the moment but might not always be true.
245 if (ConsoleUtil.TryParseConsoleFloat(MainConsole.Instance, options["client-rot-upd"], out newValue))
246 m_scene.RootRotationUpdateTolerance = newValue;
247 }
248
249 if (options.ContainsKey("client-vel-upd"))
250 {
251 float newValue;
252
253 // FIXME: This can only come from the console at the moment but might not always be true.
254 if (ConsoleUtil.TryParseConsoleFloat(MainConsole.Instance, options["client-vel-upd"], out newValue))
255 m_scene.RootVelocityUpdateTolerance = newValue;
256 }
257
258 if (options.ContainsKey("root-upd-per"))
259 {
260 int newValue;
261
262 // FIXME: This can only come from the console at the moment but might not always be true.
263 if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, options["root-upd-per"], out newValue))
264 m_scene.RootTerseUpdatePeriod = newValue;
265 }
266
267 if (options.ContainsKey("child-upd-per"))
268 {
269 int newValue;
270
271 // FIXME: This can only come from the console at the moment but might not always be true.
272 if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, options["child-upd-per"], out newValue))
273 m_scene.ChildTerseUpdatePeriod = newValue;
274 }
275
189 if (options.ContainsKey("pbackup")) 276 if (options.ContainsKey("pbackup"))
190 { 277 {
191 bool active; 278 bool active;
@@ -221,6 +308,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
221 m_scene.DebugTeleporting = enableTeleportDebugging; 308 m_scene.DebugTeleporting = enableTeleportDebugging;
222 } 309 }
223 310
311 if (options.ContainsKey("update-on-timer"))
312 {
313 bool enableUpdateOnTimer;
314 if (bool.TryParse(options["update-on-timer"], out enableUpdateOnTimer))
315 {
316 m_scene.UpdateOnTimer = enableUpdateOnTimer;
317 m_scene.Active = false;
318
319 while (m_scene.IsRunning)
320 Thread.Sleep(20);
321
322 m_scene.Active = true;
323 }
324 }
325
224 if (options.ContainsKey("updates")) 326 if (options.ContainsKey("updates"))
225 { 327 {
226 bool enableUpdateDebugging; 328 bool enableUpdateDebugging;
diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
index 8144870..e4a3382 100644
--- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
+++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
@@ -748,8 +748,8 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
748 position.X = s_tree.AbsolutePosition.X + (float)randX; 748 position.X = s_tree.AbsolutePosition.X + (float)randX;
749 position.Y = s_tree.AbsolutePosition.Y + (float)randY; 749 position.Y = s_tree.AbsolutePosition.Y + (float)randY;
750 750
751 if (position.X <= ((int)Constants.RegionSize - 1) && position.X >= 0 && 751 if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 &&
752 position.Y <= ((int)Constants.RegionSize - 1) && position.Y >= 0 && 752 position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 &&
753 Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range) 753 Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range)
754 { 754 {
755 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; 755 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
diff --git a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs
index 550b5d4..8720cc7 100644
--- a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs
+++ b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.OptionalModules.World.WorldView
55 m_WorldViewModule = fmodule; 55 m_WorldViewModule = fmodule;
56 } 56 }
57 57
58 public override byte[] Handle(string path, Stream requestData, 58 protected override byte[] ProcessRequest(string path, Stream requestData,
59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
60 { 60 {
61 httpResponse.ContentType = "image/jpeg"; 61 httpResponse.ContentType = "image/jpeg";