aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules
diff options
context:
space:
mode:
authorDr Scofield2009-02-10 13:10:57 +0000
committerDr Scofield2009-02-10 13:10:57 +0000
commit180be7de07014aa33bc6066f12a0819b731c1c9d (patch)
tree3aa13af3cda4b808fa9453655875327699b61311 /OpenSim/Region/Environment/Modules
parentStopgap measure: To use gridlaunch, or GUI, start opensim with (diff)
downloadopensim-SC_OLD-180be7de07014aa33bc6066f12a0819b731c1c9d.zip
opensim-SC_OLD-180be7de07014aa33bc6066f12a0819b731c1c9d.tar.gz
opensim-SC_OLD-180be7de07014aa33bc6066f12a0819b731c1c9d.tar.bz2
opensim-SC_OLD-180be7de07014aa33bc6066f12a0819b731c1c9d.tar.xz
this is step 2 of 2 of the OpenSim.Region.Environment refactor.
NOTHING has been deleted or moved off to forge at this point. what has happened is that OpenSim.Region.Environment.Modules has been split in two: - OpenSim.Region.CoreModules: all those modules that are either directly or indirectly referenced from other OpenSim packages, or that provide functionality that the OpenSim developer community considers core functionality: CoreModules/Agent/AssetTransaction CoreModules/Agent/Capabilities CoreModules/Agent/TextureDownload CoreModules/Agent/TextureSender CoreModules/Agent/TextureSender/Tests CoreModules/Agent/Xfer CoreModules/Avatar/AvatarFactory CoreModules/Avatar/Chat/ChatModule CoreModules/Avatar/Combat CoreModules/Avatar/Currency/SampleMoney CoreModules/Avatar/Dialog CoreModules/Avatar/Friends CoreModules/Avatar/Gestures CoreModules/Avatar/Groups CoreModules/Avatar/InstantMessage CoreModules/Avatar/Inventory CoreModules/Avatar/Inventory/Archiver CoreModules/Avatar/Inventory/Transfer CoreModules/Avatar/Lure CoreModules/Avatar/ObjectCaps CoreModules/Avatar/Profiles CoreModules/Communications/Local CoreModules/Communications/REST CoreModules/Framework/EventQueue CoreModules/Framework/InterfaceCommander CoreModules/Hypergrid CoreModules/InterGrid CoreModules/Scripting/DynamicTexture CoreModules/Scripting/EMailModules CoreModules/Scripting/HttpRequest CoreModules/Scripting/LoadImageURL CoreModules/Scripting/VectorRender CoreModules/Scripting/WorldComm CoreModules/Scripting/XMLRPC CoreModules/World/Archiver CoreModules/World/Archiver/Tests CoreModules/World/Estate CoreModules/World/Land CoreModules/World/Permissions CoreModules/World/Serialiser CoreModules/World/Sound CoreModules/World/Sun CoreModules/World/Terrain CoreModules/World/Terrain/DefaultEffects CoreModules/World/Terrain/DefaultEffects/bin CoreModules/World/Terrain/DefaultEffects/bin/Debug CoreModules/World/Terrain/Effects CoreModules/World/Terrain/FileLoaders CoreModules/World/Terrain/FloodBrushes CoreModules/World/Terrain/PaintBrushes CoreModules/World/Terrain/Tests CoreModules/World/Vegetation CoreModules/World/Wind CoreModules/World/WorldMap - OpenSim.Region.OptionalModules: all those modules that are not core modules: OptionalModules/Avatar/Chat/IRC-stuff OptionalModules/Avatar/Concierge OptionalModules/Avatar/Voice/AsterixVoice OptionalModules/Avatar/Voice/SIPVoice OptionalModules/ContentManagementSystem OptionalModules/Grid/Interregion OptionalModules/Python OptionalModules/SvnSerialiser OptionalModules/World/NPC OptionalModules/World/TreePopulator
Diffstat (limited to 'OpenSim/Region/Environment/Modules')
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs232
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs628
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs287
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs219
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs887
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs424
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Combat/CombatModule.cs154
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeModule.cs604
-rwxr-xr-xOpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeServer.py130
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs1605
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Dialog/DialogModule.cs143
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs1003
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Gestures/GesturesModule.cs104
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs223
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs170
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs655
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs426
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs279
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs247
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs389
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Lure/LureModule.cs176
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/ObjectCaps/ObjectAdd.cs368
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs145
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs292
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs202
-rw-r--r--OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs244
-rw-r--r--OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs960
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs161
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs139
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs757
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs193
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs362
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs206
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs383
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs163
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs317
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs167
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs94
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs274
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs116
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/README52
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs218
-rw-r--r--OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueGetModule.cs630
-rw-r--r--OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueHelper.cs459
-rw-r--r--OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Command.cs216
-rw-r--r--OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Commander.cs182
-rw-r--r--OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs43
-rw-r--r--OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs199
-rw-r--r--OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs77
-rw-r--r--OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneAssetService.cs201
-rw-r--r--OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneInventoryService.cs314
-rw-r--r--OpenSim/Region/Environment/Modules/Hypergrid/HGWorldMapModule.cs178
-rw-r--r--OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs1273
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs332
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/EMailModules/EmailModule.cs288
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs437
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs229
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs515
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs726
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs726
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs128
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs460
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs161
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs333
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/ArchiverModule.cs95
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/AssetsArchiver.cs143
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/AssetsDearchiver.cs184
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/AssetsRequest.cs138
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs258
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveReader.cs195
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs202
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/Tests/ArchiverTests.cs188
-rw-r--r--OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs1012
-rw-r--r--OpenSim/Region/Environment/Modules/World/Estate/EstateTerrainXferHandler.cs127
-rw-r--r--OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs188
-rw-r--r--OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs1347
-rw-r--r--OpenSim/Region/Environment/Modules/World/Land/LandObject.cs930
-rw-r--r--OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs1060
-rw-r--r--OpenSim/Region/Environment/Modules/World/NPC/NPCModule.cs68
-rw-r--r--OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs1498
-rw-r--r--OpenSim/Region/Environment/Modules/World/Serialiser/IFileSerialiser.cs36
-rw-r--r--OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseObjects.cs125
-rw-r--r--OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseTerrain.cs53
-rw-r--r--OpenSim/Region/Environment/Modules/World/Serialiser/SerialiserModule.cs226
-rw-r--r--OpenSim/Region/Environment/Modules/World/Sound/SoundModule.cs97
-rw-r--r--OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs434
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/Effects/CookieCutter.cs125
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/Effects/DefaultTerrainGenerator.cs56
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/BMP.cs76
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GIF.cs61
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GenericSystemDrawing.cs195
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/JPEG.cs112
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/LLRAW.cs250
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/PNG.cs61
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/RAW32.cs170
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/TIFF.cs61
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/Terragen.cs142
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/FlattenArea.cs70
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/LowerArea.cs54
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/NoiseArea.cs58
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RaiseArea.cs54
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RevertArea.cs67
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/SmoothArea.cs114
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/ITerrainEffect.cs36
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/ITerrainFloodEffect.cs37
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/ITerrainLoader.cs42
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/ITerrainModule.cs61
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/ITerrainPaintableEffect.cs36
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs318
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/FlattenSphere.cs101
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/LowerSphere.cs84
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/NoiseSphere.cs67
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/OlsenSphere.cs223
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RaiseSphere.cs80
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RevertSphere.cs80
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/SmoothSphere.cs100
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/WeatherSphere.cs211
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/TerrainException.cs46
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/TerrainModule.cs1001
-rw-r--r--OpenSim/Region/Environment/Modules/World/Terrain/Tests/TerrainTest.cs118
-rw-r--r--OpenSim/Region/Environment/Modules/World/TreePopulator/TreePopulatorModule.cs304
-rw-r--r--OpenSim/Region/Environment/Modules/World/Vegetation/VegetationModule.cs118
-rw-r--r--OpenSim/Region/Environment/Modules/World/Wind/WindModule.cs207
-rw-r--r--OpenSim/Region/Environment/Modules/World/WorldMap/IMapTileTerrainRenderer.cs39
-rw-r--r--OpenSim/Region/Environment/Modules/World/WorldMap/MapImageModule.cs586
-rw-r--r--OpenSim/Region/Environment/Modules/World/WorldMap/MapSearchModule.cs172
-rw-r--r--OpenSim/Region/Environment/Modules/World/WorldMap/ShadedMapTileRenderer.cs249
-rw-r--r--OpenSim/Region/Environment/Modules/World/WorldMap/TexturedMapTileRenderer.cs411
-rw-r--r--OpenSim/Region/Environment/Modules/World/WorldMap/WorldMapModule.cs905
129 files changed, 0 insertions, 38867 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
deleted file mode 100644
index 1ac0807..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ /dev/null
@@ -1,232 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31
32using System.Threading;
33using OpenMetaverse;
34using log4net;
35using Nini.Config;
36using OpenSim.Framework;
37using OpenSim.Framework.Communications.Cache;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40
41namespace OpenSim.Region.Environment.Modules.Avatar.AvatarFactory
42{
43 public class AvatarFactoryModule : IAvatarFactory, IRegionModule
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 private Scene m_scene = null;
47 private static readonly AvatarAppearance def = new AvatarAppearance();
48
49 public bool TryGetAvatarAppearance(UUID avatarId, out AvatarAppearance appearance)
50 {
51 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(avatarId);
52 //if ((profile != null) && (profile.RootFolder != null))
53 if (profile != null)
54 {
55 appearance = m_scene.CommsManager.AvatarService.GetUserAppearance(avatarId);
56 if (appearance != null)
57 {
58 //SetAppearanceAssets(profile, ref appearance);
59 //m_log.DebugFormat("[APPEARANCE]: Found : {0}", appearance.ToString());
60 return true;
61 }
62 }
63
64 appearance = CreateDefault(avatarId);
65 m_log.ErrorFormat("[APPEARANCE]: Appearance not found for {0}, creating default", avatarId);
66 return false;
67 }
68
69 private AvatarAppearance CreateDefault(UUID avatarId)
70 {
71 AvatarAppearance appearance = null;
72 AvatarWearable[] wearables;
73 byte[] visualParams;
74 GetDefaultAvatarAppearance(out wearables, out visualParams);
75 appearance = new AvatarAppearance(avatarId, wearables, visualParams);
76
77 return appearance;
78 }
79
80 public void Initialise(Scene scene, IConfigSource source)
81 {
82 scene.RegisterModuleInterface<IAvatarFactory>(this);
83 scene.EventManager.OnNewClient += NewClient;
84
85 if (m_scene == null)
86 {
87 m_scene = scene;
88 }
89
90 }
91
92 public void PostInitialise()
93 {
94 }
95
96 public void Close()
97 {
98 }
99
100 public string Name
101 {
102 get { return "Default Avatar Factory"; }
103 }
104
105 public bool IsSharedModule
106 {
107 get { return false; }
108 }
109
110 public void NewClient(IClientAPI client)
111 {
112 client.OnAvatarNowWearing += AvatarIsWearing;
113 }
114
115 public void RemoveClient(IClientAPI client)
116 {
117 // client.OnAvatarNowWearing -= AvatarIsWearing;
118 }
119
120
121 public void SetAppearanceAssets(CachedUserInfo profile, ref AvatarAppearance appearance)
122 {
123 if (profile.RootFolder != null)
124 {
125 for (int i = 0; i < 13; i++)
126 {
127 if (appearance.Wearables[i].ItemID == UUID.Zero)
128 {
129 appearance.Wearables[i].AssetID = UUID.Zero;
130 }
131 else
132 {
133 InventoryItemBase baseItem = profile.RootFolder.FindItem(appearance.Wearables[i].ItemID);
134
135 if (baseItem != null)
136 {
137 appearance.Wearables[i].AssetID = baseItem.AssetID;
138 }
139 else
140 {
141 m_log.ErrorFormat("[APPEARANCE]: Can't find inventory item {0}, setting to default", appearance.Wearables[i].ItemID);
142 appearance.Wearables[i].AssetID = def.Wearables[i].AssetID;
143 }
144 }
145 }
146 }
147 else
148 {
149 m_log.Error("[APPEARANCE]: you have no inventory, appearance stuff isn't going to work");
150 }
151 }
152
153 /// <summary>
154 /// Update what the avatar is wearing using an item from their inventory.
155 /// </summary>
156 /// <param name="sender"></param>
157 /// <param name="e"></param>
158 public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
159 {
160 IClientAPI clientView = (IClientAPI)sender;
161 ScenePresence avatar = m_scene.GetScenePresence(clientView.AgentId);
162
163 if (avatar == null)
164 {
165 m_log.Error("[APPEARANCE]: Avatar is child agent, ignoring AvatarIsWearing event");
166 return;
167 }
168
169 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId);
170
171 AvatarAppearance avatAppearance = null;
172 if (!TryGetAvatarAppearance(clientView.AgentId, out avatAppearance))
173 {
174 m_log.Warn("[APPEARANCE]: We didn't seem to find the appearance, falling back to ScenePresence");
175 avatAppearance = avatar.Appearance;
176 }
177
178 //m_log.DebugFormat("[APPEARANCE]: Received wearables for {0}", clientView.Name);
179
180 if (profile != null)
181 {
182 if (profile.RootFolder != null)
183 {
184 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
185 {
186 if (wear.Type < 13)
187 {
188 avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID;
189 }
190 }
191
192 SetAppearanceAssets(profile, ref avatAppearance);
193
194 m_scene.CommsManager.AvatarService.UpdateUserAppearance(clientView.AgentId, avatAppearance);
195 avatar.Appearance = avatAppearance;
196 }
197 else
198 {
199 m_log.WarnFormat(
200 "[APPEARANCE]: Inventory has not yet been received for {0}, cannot set wearables",
201 clientView.Name);
202 }
203 }
204 else
205 {
206 m_log.WarnFormat("[APPEARANCE]: Cannot set wearables for {0}, no user profile found", clientView.Name);
207 }
208 }
209
210 public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams)
211 {
212 visualParams = GetDefaultVisualParams();
213 wearables = AvatarWearable.DefaultWearables;
214 }
215
216 public void UpdateDatabase(UUID user, AvatarAppearance appearance)
217 {
218 m_scene.CommsManager.AvatarService.UpdateUserAppearance(user, appearance);
219 }
220
221 private static byte[] GetDefaultVisualParams()
222 {
223 byte[] visualParams;
224 visualParams = new byte[218];
225 for (int i = 0; i < 218; i++)
226 {
227 visualParams[i] = 100;
228 }
229 return visualParams;
230 }
231 }
232}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs
deleted file mode 100644
index dfa1caa..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs
+++ /dev/null
@@ -1,628 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text.RegularExpressions;
32using log4net;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38namespace OpenSim.Region.Environment.Modules.Avatar.Chat
39{
40
41 // An instance of this class exists for each unique combination of
42 // IRC chat interface characteristics, as determined by the supplied
43 // configuration file.
44
45 internal class ChannelState
46 {
47
48 private static readonly ILog m_log =
49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private static Regex arg = new Regex(@"\[[^\[\]]*\]");
52 private static int _idk_ = 0;
53 private static int DEBUG_CHANNEL = 2147483647;
54
55 // These are the IRC Connector configurable parameters with hard-wired
56 // default values (retained for compatability).
57
58 internal string Server = null;
59 internal string Password = null;
60 internal string IrcChannel = null;
61 internal string BaseNickname = "OSimBot";
62 internal uint Port = 6667;
63 internal string User = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot";
64
65 internal bool ClientReporting = true;
66 internal bool RelayChat = true;
67 internal bool RelayPrivateChannels = false;
68 internal int RelayChannel = 1;
69 internal List<int> ValidInWorldChannels = new List<int>();
70
71 // Connector agnostic parameters. These values are NOT shared with the
72 // connector and do not differentiate at an IRC level
73
74 internal string PrivateMessageFormat = "PRIVMSG {0} :<{2}> {1} {3}";
75 internal string NoticeMessageFormat = "PRIVMSG {0} :<{2}> {3}";
76 internal int RelayChannelOut = -1;
77 internal bool RandomizeNickname = true;
78 internal bool CommandsEnabled = false;
79 internal int CommandChannel = -1;
80 internal int ConnectDelay = 10;
81 internal int PingDelay = 15;
82 internal string DefaultZone = "Sim";
83
84 internal string _accessPassword = String.Empty;
85 internal Regex AccessPasswordRegex = null;
86 internal string AccessPassword
87 {
88 get { return _accessPassword; }
89 set
90 {
91 _accessPassword = value;
92 AccessPasswordRegex = new Regex(String.Format(@"^{0},\s*(?<avatar>[^,]+),\s*(?<message>.+)$", _accessPassword),
93 RegexOptions.Compiled);
94 }
95 }
96
97
98
99 // IRC connector reference
100
101 internal IRCConnector irc = null;
102
103 internal int idn = _idk_++;
104
105 // List of regions dependent upon this connection
106
107 internal List<RegionState> clientregions = new List<RegionState>();
108
109 // Needed by OpenChannel
110
111 internal ChannelState()
112 {
113 }
114
115 // This constructor is used by the Update* methods. A copy of the
116 // existing channel state is created, and distinguishing characteristics
117 // are copied across.
118
119 internal ChannelState(ChannelState model)
120 {
121 Server = model.Server;
122 Password = model.Password;
123 IrcChannel = model.IrcChannel;
124 Port = model.Port;
125 BaseNickname = model.BaseNickname;
126 RandomizeNickname = model.RandomizeNickname;
127 User = model.User;
128 CommandsEnabled = model.CommandsEnabled;
129 CommandChannel = model.CommandChannel;
130 RelayChat = model.RelayChat;
131 RelayPrivateChannels = model.RelayPrivateChannels;
132 RelayChannelOut = model.RelayChannelOut;
133 RelayChannel = model.RelayChannel;
134 ValidInWorldChannels = model.ValidInWorldChannels;
135 PrivateMessageFormat = model.PrivateMessageFormat;
136 NoticeMessageFormat = model.NoticeMessageFormat;
137 ClientReporting = model.ClientReporting;
138 AccessPassword = model.AccessPassword;
139 DefaultZone = model.DefaultZone;
140 ConnectDelay = model.ConnectDelay;
141 PingDelay = model.PingDelay;
142 }
143
144 // Read the configuration file, performing variable substitution and any
145 // necessary aliasing. See accompanying documentation for how this works.
146 // If you don't need variables, then this works exactly as before.
147 // If either channel or server are not specified, the request fails.
148
149 internal static void OpenChannel(RegionState rs, IConfig config)
150 {
151
152 // Create a new instance of a channel. This may not actually
153 // get used if an equivalent channel already exists.
154
155 ChannelState cs = new ChannelState();
156
157 // Read in the configuration file and filter everything for variable
158 // subsititution.
159
160 m_log.DebugFormat("[IRC-Channel-{0}] Initial request by Region {1} to connect to IRC", cs.idn, rs.Region);
161
162 cs.Server = Substitute(rs, config.GetString("server", null));
163 m_log.DebugFormat("[IRC-Channel-{0}] Server : <{1}>", cs.idn, cs.Server);
164 cs.Password = Substitute(rs, config.GetString("password", null));
165 // probably not a good idea to put a password in the log file
166 cs.IrcChannel = Substitute(rs, config.GetString("channel", null));
167 m_log.DebugFormat("[IRC-Channel-{0}] IrcChannel : <{1}>", cs.idn, cs.IrcChannel);
168 cs.Port = Convert.ToUInt32(Substitute(rs, config.GetString("port", Convert.ToString(cs.Port))));
169 m_log.DebugFormat("[IRC-Channel-{0}] Port : <{1}>", cs.idn, cs.Port);
170 cs.BaseNickname = Substitute(rs, config.GetString("nick", cs.BaseNickname));
171 m_log.DebugFormat("[IRC-Channel-{0}] BaseNickname : <{1}>", cs.idn, cs.BaseNickname);
172 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("randomize_nick", Convert.ToString(cs.RandomizeNickname))));
173 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
174 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("nicknum", Convert.ToString(cs.RandomizeNickname))));
175 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
176 cs.User = Substitute(rs, config.GetString("username", cs.User));
177 m_log.DebugFormat("[IRC-Channel-{0}] User : <{1}>", cs.idn, cs.User);
178 cs.CommandsEnabled = Convert.ToBoolean(Substitute(rs, config.GetString("commands_enabled", Convert.ToString(cs.CommandsEnabled))));
179 m_log.DebugFormat("[IRC-Channel-{0}] CommandsEnabled : <{1}>", cs.idn, cs.CommandsEnabled);
180 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("commandchannel", Convert.ToString(cs.CommandChannel))));
181 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
182 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("command_channel", Convert.ToString(cs.CommandChannel))));
183 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
184 cs.RelayChat = Convert.ToBoolean(Substitute(rs, config.GetString("relay_chat", Convert.ToString(cs.RelayChat))));
185 m_log.DebugFormat("[IRC-Channel-{0}] RelayChat : <{1}>", cs.idn, cs.RelayChat);
186 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("relay_private_channels", Convert.ToString(cs.RelayPrivateChannels))));
187 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
188 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("useworldcomm", Convert.ToString(cs.RelayPrivateChannels))));
189 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
190 cs.RelayChannelOut = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_out", Convert.ToString(cs.RelayChannelOut))));
191 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannelOut : <{1}>", cs.idn, cs.RelayChannelOut);
192 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_in", Convert.ToString(cs.RelayChannel))));
193 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
194 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("inchannel", Convert.ToString(cs.RelayChannel))));
195 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
196 cs.PrivateMessageFormat = Substitute(rs, config.GetString("msgformat", cs.PrivateMessageFormat));
197 m_log.DebugFormat("[IRC-Channel-{0}] PrivateMessageFormat : <{1}>", cs.idn, cs.PrivateMessageFormat);
198 cs.NoticeMessageFormat = Substitute(rs, config.GetString("noticeformat", cs.NoticeMessageFormat));
199 m_log.DebugFormat("[IRC-Channel-{0}] NoticeMessageFormat : <{1}>", cs.idn, cs.NoticeMessageFormat);
200 cs.ClientReporting = Convert.ToInt32(Substitute(rs, config.GetString("verbosity", cs.ClientReporting?"1":"0"))) > 0;
201 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
202 cs.ClientReporting = Convert.ToBoolean(Substitute(rs, config.GetString("report_clients", Convert.ToString(cs.ClientReporting))));
203 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
204 cs.DefaultZone = Substitute(rs, config.GetString("fallback_region", cs.DefaultZone));
205 m_log.DebugFormat("[IRC-Channel-{0}] DefaultZone : <{1}>", cs.idn, cs.DefaultZone);
206 cs.ConnectDelay = Convert.ToInt32(Substitute(rs, config.GetString("connect_delay", Convert.ToString(cs.ConnectDelay))));
207 m_log.DebugFormat("[IRC-Channel-{0}] ConnectDelay : <{1}>", cs.idn, cs.ConnectDelay);
208 cs.PingDelay = Convert.ToInt32(Substitute(rs, config.GetString("ping_delay", Convert.ToString(cs.PingDelay))));
209 m_log.DebugFormat("[IRC-Channel-{0}] PingDelay : <{1}>", cs.idn, cs.PingDelay);
210 cs.AccessPassword = Substitute(rs, config.GetString("access_password", cs.AccessPassword));
211 m_log.DebugFormat("[IRC-Channel-{0}] AccessPassword : <{1}>", cs.idn, cs.AccessPassword);
212
213
214 // Fail if fundamental information is still missing
215
216 if (cs.Server == null || cs.IrcChannel == null || cs.BaseNickname == null || cs.User == null)
217 throw new Exception(String.Format("[IRC-Channel-{0}] Invalid configuration for region {1}", cs.idn, rs.Region));
218
219 m_log.InfoFormat("[IRC-Channel-{0}] Configuration for Region {1} is valid", cs.idn, rs.Region);
220 m_log.InfoFormat("[IRC-Channel-{0}] Server = {1}", cs.idn, cs.Server);
221 m_log.InfoFormat("[IRC-Channel-{0}] Channel = {1}", cs.idn, cs.IrcChannel);
222 m_log.InfoFormat("[IRC-Channel-{0}] Port = {1}", cs.idn, cs.Port);
223 m_log.InfoFormat("[IRC-Channel-{0}] Nickname = {1}", cs.idn, cs.BaseNickname);
224 m_log.InfoFormat("[IRC-Channel-{0}] User = {1}", cs.idn, cs.User);
225
226 // Set the channel state for this region
227
228 if (cs.RelayChat)
229 {
230 cs.ValidInWorldChannels.Add(0);
231 cs.ValidInWorldChannels.Add(DEBUG_CHANNEL);
232 }
233
234 if (cs.RelayPrivateChannels)
235 cs.ValidInWorldChannels.Add(cs.RelayChannelOut);
236
237 rs.cs = Integrate(rs, cs);
238
239 }
240
241 // An initialized channel state instance is passed in. If an identical
242 // channel state instance already exists, then the existing instance
243 // is used to replace the supplied value.
244 // If the instance matches with respect to IRC, then the underlying
245 // IRCConnector is assigned to the supplied channel state and the
246 // updated value is returned.
247 // If there is no match, then the supplied instance is completed by
248 // creating and assigning an instance of an IRC connector.
249
250 private static ChannelState Integrate(RegionState rs, ChannelState p_cs)
251 {
252
253 ChannelState cs = p_cs;
254
255 // Check to see if we have an existing server/channel setup that can be used
256 // In the absence of variable substitution this will always resolve to the
257 // same ChannelState instance, and the table will only contains a single
258 // entry, so the performance considerations for the existing behavior are
259 // zero. Only the IRC connector is shared, the ChannelState still contains
260 // values that, while independent of the IRC connetion, do still distinguish
261 // this region's behavior.
262
263 lock (IRCBridgeModule.m_channels)
264 {
265
266 foreach (ChannelState xcs in IRCBridgeModule.m_channels)
267 {
268 if (cs.IsAPerfectMatchFor(xcs))
269 {
270 m_log.DebugFormat("[IRC-Channel-{0}] Channel state matched", cs.idn);
271 cs = xcs;
272 break;
273 }
274 if (cs.IsAConnectionMatchFor(xcs))
275 {
276 m_log.DebugFormat("[IRC-Channel-{0}] Channel matched", cs.idn);
277 cs.irc = xcs.irc;
278 break;
279 }
280 }
281
282 }
283
284 // No entry was found, so this is going to be a new entry.
285
286 if (cs.irc == null)
287 {
288
289 m_log.DebugFormat("[IRC-Channel-{0}] New channel required", cs.idn);
290
291 if ((cs.irc = new IRCConnector(cs)) != null)
292 {
293
294 IRCBridgeModule.m_channels.Add(cs);
295
296 m_log.InfoFormat("[IRC-Channel-{0}] New channel initialized for {1}, nick: {2}, commands {3}, private channels {4}",
297 cs.idn, rs.Region, cs.DefaultZone,
298 cs.CommandsEnabled ? "enabled" : "not enabled",
299 cs.RelayPrivateChannels ? "relayed" : "not relayed");
300 }
301 else
302 {
303 string txt = String.Format("[IRC-Channel-{0}] Region {1} failed to connect to channel {2} on server {3}:{4}",
304 cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
305 m_log.Error(txt);
306 throw new Exception(txt);
307 }
308 }
309 else
310 {
311 m_log.InfoFormat("[IRC-Channel-{0}] Region {1} reusing existing connection to channel {2} on server {3}:{4}",
312 cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
313 }
314
315 m_log.InfoFormat("[IRC-Channel-{0}] Region {1} associated with channel {2} on server {3}:{4}",
316 cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
317
318 // We're finally ready to commit ourselves
319
320
321 return cs;
322
323 }
324
325 // These routines allow differentiating changes to
326 // the underlying channel state. If necessary, a
327 // new channel state will be created.
328
329 internal ChannelState UpdateServer(RegionState rs, string server)
330 {
331 RemoveRegion(rs);
332 ChannelState cs = new ChannelState(this);
333 cs.Server = server;
334 cs = Integrate(rs, cs);
335 cs.AddRegion(rs);
336 return cs;
337 }
338
339 internal ChannelState UpdatePort(RegionState rs, string port)
340 {
341 RemoveRegion(rs);
342 ChannelState cs = new ChannelState(this);
343 cs.Port = Convert.ToUInt32(port);
344 cs = Integrate(rs, cs);
345 cs.AddRegion(rs);
346 return cs;
347 }
348
349 internal ChannelState UpdateChannel(RegionState rs, string channel)
350 {
351 RemoveRegion(rs);
352 ChannelState cs = new ChannelState(this);
353 cs.IrcChannel = channel;
354 cs = Integrate(rs, cs);
355 cs.AddRegion(rs);
356 return cs;
357 }
358
359 internal ChannelState UpdateNickname(RegionState rs, string nickname)
360 {
361 RemoveRegion(rs);
362 ChannelState cs = new ChannelState(this);
363 cs.BaseNickname = nickname;
364 cs = Integrate(rs, cs);
365 cs.AddRegion(rs);
366 return cs;
367 }
368
369 internal ChannelState UpdateClientReporting(RegionState rs, string cr)
370 {
371 RemoveRegion(rs);
372 ChannelState cs = new ChannelState(this);
373 cs.ClientReporting = Convert.ToBoolean(cr);
374 cs = Integrate(rs, cs);
375 cs.AddRegion(rs);
376 return cs;
377 }
378
379 internal ChannelState UpdateRelayIn(RegionState rs, string channel)
380 {
381 RemoveRegion(rs);
382 ChannelState cs = new ChannelState(this);
383 cs.RelayChannel = Convert.ToInt32(channel);
384 cs = Integrate(rs, cs);
385 cs.AddRegion(rs);
386 return cs;
387 }
388
389 internal ChannelState UpdateRelayOut(RegionState rs, string channel)
390 {
391 RemoveRegion(rs);
392 ChannelState cs = new ChannelState(this);
393 cs.RelayChannelOut = Convert.ToInt32(channel);
394 cs = Integrate(rs, cs);
395 cs.AddRegion(rs);
396 return cs;
397 }
398
399 // Determine whether or not this is a 'new' channel. Only those
400 // attributes that uniquely distinguish an IRC connection should
401 // be included here (and only those attributes should really be
402 // in the ChannelState structure)
403
404 private bool IsAConnectionMatchFor(ChannelState cs)
405 {
406 return (
407 Server == cs.Server &&
408 IrcChannel == cs.IrcChannel &&
409 Port == cs.Port &&
410 BaseNickname == cs.BaseNickname &&
411 User == cs.User
412 );
413 }
414
415 // This level of obsessive matching allows us to produce
416 // a minimal overhead int he case of a server which does
417 // need to differentiate IRC at a region level.
418
419 private bool IsAPerfectMatchFor(ChannelState cs)
420 {
421 return ( IsAConnectionMatchFor(cs) &&
422 RelayChannelOut == cs.RelayChannelOut &&
423 PrivateMessageFormat == cs.PrivateMessageFormat &&
424 NoticeMessageFormat == cs.NoticeMessageFormat &&
425 RandomizeNickname == cs.RandomizeNickname &&
426 AccessPassword == cs.AccessPassword &&
427 CommandsEnabled == cs.CommandsEnabled &&
428 CommandChannel == cs.CommandChannel &&
429 DefaultZone == cs.DefaultZone &&
430 RelayPrivateChannels == cs.RelayPrivateChannels &&
431 RelayChannel == cs.RelayChannel &&
432 RelayChat == cs.RelayChat &&
433 ClientReporting == cs.ClientReporting
434 );
435 }
436
437 // This function implements the variable substitution mechanism
438 // for the configuration values. Each string read from the
439 // configuration file is scanned for '[...]' enclosures. Each
440 // one that is found is replaced by either a runtime variable
441 // (%xxx) or an existing configuration key. When no further
442 // substitution is possible, the remaining string is returned
443 // to the caller. This allows for arbitrarily nested
444 // enclosures.
445
446 private static string Substitute(RegionState rs, string instr)
447 {
448
449 string result = instr;
450
451 if (result == null || result.Length == 0)
452 return result;
453
454 // Repeatedly scan the string until all possible
455 // substitutions have been performed.
456
457 // m_log.DebugFormat("[IRC-Channel] Parse[1]: {0}", result);
458
459 while (arg.IsMatch(result))
460 {
461
462 string vvar = arg.Match(result).ToString();
463 string var = vvar.Substring(1,vvar.Length-2).Trim();
464
465 switch (var.ToLower())
466 {
467 case "%region" :
468 result = result.Replace(vvar, rs.Region);
469 break;
470 case "%host" :
471 result = result.Replace(vvar, rs.Host);
472 break;
473 case "%master1" :
474 result = result.Replace(vvar, rs.MA1);
475 break;
476 case "%master2" :
477 result = result.Replace(vvar, rs.MA2);
478 break;
479 case "%locx" :
480 result = result.Replace(vvar, rs.LocX);
481 break;
482 case "%locy" :
483 result = result.Replace(vvar, rs.LocY);
484 break;
485 case "%k" :
486 result = result.Replace(vvar, rs.IDK);
487 break;
488 default :
489 result = result.Replace(vvar, rs.config.GetString(var,var));
490 break;
491 }
492 // m_log.DebugFormat("[IRC-Channel] Parse[2]: {0}", result);
493 }
494
495 // m_log.DebugFormat("[IRC-Channel] Parse[3]: {0}", result);
496 return result;
497
498 }
499
500 public void Close()
501 {
502 m_log.InfoFormat("[IRC-Channel-{0}] Closing channel <{1}> to server <{2}:{3}>",
503 idn, IrcChannel, Server, Port);
504 m_log.InfoFormat("[IRC-Channel-{0}] There are {1} active clients",
505 idn, clientregions.Count);
506 irc.Close();
507 }
508
509 public void Open()
510 {
511 m_log.InfoFormat("[IRC-Channel-{0}] Opening channel <{1}> to server <{2}:{3}>",
512 idn, IrcChannel, Server, Port);
513
514 irc.Open();
515
516 }
517
518 // These are called by each region that attaches to this channel. The call affects
519 // only the relationship of the region with the channel. Not the channel to IRC
520 // relationship (unless it is closed and we want it open).
521
522 public void Open(RegionState rs)
523 {
524 AddRegion(rs);
525 Open();
526 }
527
528 // Close is called to ensure that the IRC session is terminated if this is the
529 // only client.
530
531 public void Close(RegionState rs)
532 {
533 RemoveRegion(rs);
534 lock (IRCBridgeModule.m_channels)
535 {
536 if (clientregions.Count == 0)
537 {
538 Close();
539 IRCBridgeModule.m_channels.Remove(this);
540 m_log.InfoFormat("[IRC-Channel-{0}] Region {1} is last user of channel <{2}> to server <{3}:{4}>",
541 idn, rs.Region, IrcChannel, Server, Port);
542 m_log.InfoFormat("[IRC-Channel-{0}] Removed", idn);
543 }
544 }
545 }
546
547 // Add a client region to this channel if it is not already known
548
549 public void AddRegion(RegionState rs)
550 {
551 m_log.InfoFormat("[IRC-Channel-{0}] Adding region {1} to channel <{2}> to server <{3}:{4}>",
552 idn, rs.Region, IrcChannel, Server, Port);
553 if (!clientregions.Contains(rs))
554 {
555 clientregions.Add(rs);
556 lock (irc) irc.depends++;
557 }
558 }
559
560 // Remove a client region from the channel. If this is the last
561 // region, then clean up the channel. The connector will clean itself
562 // up if it finds itself about to be GC'd.
563
564 public void RemoveRegion(RegionState rs)
565 {
566
567 m_log.InfoFormat("[IRC-Channel-{0}] Removing region {1} from channel <{2} to server <{3}:{4}>",
568 idn, rs.Region, IrcChannel, Server, Port);
569
570 if (clientregions.Contains(rs))
571 {
572 clientregions.Remove(rs);
573 lock (irc) irc.depends--;
574 }
575
576 }
577
578 // This function is lifted from the IRCConnector because it
579 // contains information that is not differentiating from an
580 // IRC point-of-view.
581
582 public static void OSChat(IRCConnector p_irc, OSChatMessage c, bool cmsg)
583 {
584
585 // m_log.DebugFormat("[IRC-OSCHAT] from {0}:{1}", p_irc.Server, p_irc.IrcChannel);
586
587 try
588 {
589
590 // Scan through the set of unique channel configuration for those
591 // that belong to this connector. And then forward the message to
592 // all regions known to those channels.
593 // Note that this code is responsible for completing some of the
594 // settings for the inbound OSChatMessage
595
596 lock (IRCBridgeModule.m_channels)
597 {
598 foreach (ChannelState cs in IRCBridgeModule.m_channels)
599 {
600 if ( p_irc == cs.irc)
601 {
602
603 // This non-IRC differentiator moved to here
604
605 if (cmsg && !cs.ClientReporting)
606 continue;
607
608 // This non-IRC differentiator moved to here
609
610 c.Channel = (cs.RelayPrivateChannels ? cs.RelayChannel : 0);
611
612 foreach (RegionState region in cs.clientregions)
613 {
614 region.OSChat(cs.irc, c);
615 }
616
617 }
618 }
619 }
620 }
621 catch (Exception ex)
622 {
623 m_log.ErrorFormat("[IRC-OSCHAT]: BroadcastSim Exception: {0}", ex.Message);
624 m_log.Debug(ex);
625 }
626 }
627 }
628}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs
deleted file mode 100644
index f234b75..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs
+++ /dev/null
@@ -1,287 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Net.Sockets;
32using System.Reflection;
33using System.Text.RegularExpressions;
34using System.Threading;
35using OpenMetaverse;
36using log4net;
37using Nini.Config;
38using OpenSim.Framework;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.Environment.Modules.Avatar.Chat
43{
44 public class ChatModule : IRegionModule
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private const int DEBUG_CHANNEL = 2147483647;
50
51 private bool m_enabled = true;
52 private int m_saydistance = 30;
53 private int m_shoutdistance = 100;
54 private int m_whisperdistance = 10;
55 private List<Scene> m_scenes = new List<Scene>();
56
57 internal object m_syncInit = new object();
58
59 #region IRegionModule Members
60 public virtual void Initialise(Scene scene, IConfigSource config)
61 {
62 // wrap this in a try block so that defaults will work if
63 // the config file doesn't specify otherwise.
64 try
65 {
66 m_enabled = config.Configs["Chat"].GetBoolean("enabled", m_enabled);
67 if (!m_enabled) return;
68
69 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
70 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
71 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
72 }
73 catch (Exception)
74 {
75 }
76
77 lock (m_syncInit)
78 {
79 if (!m_scenes.Contains(scene))
80 {
81 m_scenes.Add(scene);
82 scene.EventManager.OnNewClient += OnNewClient;
83 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
84 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
85 }
86 }
87
88 m_log.InfoFormat("[CHAT] initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
89 m_whisperdistance, m_saydistance, m_shoutdistance);
90 }
91 public virtual void PostInitialise()
92 {
93 }
94
95 public virtual void Close()
96 {
97 }
98
99 public virtual string Name
100 {
101 get { return "ChatModule"; }
102 }
103
104 public virtual bool IsSharedModule
105 {
106 get { return true; }
107 }
108
109 #endregion
110
111
112 public virtual void OnNewClient(IClientAPI client)
113 {
114 client.OnChatFromClient += OnChatFromClient;
115 }
116
117 protected OSChatMessage FixPositionOfChatMessage(OSChatMessage c)
118 {
119 ScenePresence avatar;
120 Scene scene = (Scene)c.Scene;
121 if ((avatar = scene.GetScenePresence(c.Sender.AgentId)) != null)
122 c.Position = avatar.AbsolutePosition;
123
124 return c;
125 }
126
127 public virtual void OnChatFromClient(Object sender, OSChatMessage c)
128 {
129 c = FixPositionOfChatMessage(c);
130
131 // redistribute to interested subscribers
132 Scene scene = (Scene)c.Scene;
133 scene.EventManager.TriggerOnChatFromClient(sender, c);
134
135 // early return if not on public or debug channel
136 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return;
137
138 // sanity check:
139 if (c.Sender == null)
140 {
141 m_log.ErrorFormat("[CHAT] OnChatFromClient from {0} has empty Sender field!", sender);
142 return;
143 }
144
145 DeliverChatToAvatars(ChatSourceType.Agent, c);
146 }
147
148 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
149 {
150 // early return if not on public or debug channel
151 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return;
152
153 DeliverChatToAvatars(ChatSourceType.Object, c);
154 }
155
156 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
157 {
158 string fromName = c.From;
159 UUID fromID = UUID.Zero;
160 string message = c.Message;
161 IScene scene = c.Scene;
162 Vector3 fromPos = c.Position;
163 Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize,
164 scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
165
166 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
167
168 switch (sourceType)
169 {
170 case ChatSourceType.Agent:
171 if (!(scene is Scene))
172 {
173 m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}",
174 scene.RegionInfo.RegionName, c.Sender.AgentId);
175 return;
176 }
177 ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId);
178 fromPos = avatar.AbsolutePosition;
179 fromName = avatar.Name;
180 fromID = c.Sender.AgentId;
181
182 break;
183
184 case ChatSourceType.Object:
185 fromID = c.SenderUUID;
186
187 break;
188 }
189
190 // TODO: iterate over message
191 if (message.Length >= 1000) // libomv limit
192 message = message.Substring(0, 1000);
193
194 // m_log.DebugFormat("[CHAT]: DCTA: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, c.Type, sourceType);
195
196 foreach (Scene s in m_scenes)
197 {
198 s.ForEachScenePresence(delegate(ScenePresence presence)
199 {
200 TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName,
201 c.Type, message, sourceType);
202 });
203 }
204 }
205
206
207 static private Vector3 CenterOfRegion = new Vector3(128, 128, 30);
208 public virtual void OnChatBroadcast(Object sender, OSChatMessage c)
209 {
210 // unless the chat to be broadcast is of type Region, we
211 // drop it if its channel is neither 0 nor DEBUG_CHANNEL
212 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL && c.Type != ChatTypeEnum.Region) return;
213
214 ChatTypeEnum cType = c.Type;
215 if (c.Channel == DEBUG_CHANNEL)
216 cType = ChatTypeEnum.DebugChannel;
217
218 if (cType == ChatTypeEnum.Region)
219 cType = ChatTypeEnum.Say;
220
221 if (c.Message.Length > 1100)
222 c.Message = c.Message.Substring(0, 1000);
223
224 // broadcast chat works by redistributing every incoming chat
225 // message to each avatar in the scene.
226 string fromName = c.From;
227
228 UUID fromID = UUID.Zero;
229 ChatSourceType sourceType = ChatSourceType.Object;
230 if (null != c.Sender)
231 {
232 ScenePresence avatar = (c.Scene as Scene).GetScenePresence(c.Sender.AgentId);
233 fromID = c.Sender.AgentId;
234 fromName = avatar.Name;
235 sourceType = ChatSourceType.Agent;
236 }
237
238 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
239
240 ((Scene)c.Scene).ForEachScenePresence(
241 delegate(ScenePresence presence)
242 {
243 // ignore chat from child agents
244 if (presence.IsChildAgent) return;
245
246 IClientAPI client = presence.ControllingClient;
247
248 // don't forward SayOwner chat from objects to
249 // non-owner agents
250 if ((c.Type == ChatTypeEnum.Owner) &&
251 (null != c.SenderObject) &&
252 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
253 return;
254
255 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID,
256 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
257 });
258 }
259
260
261 protected virtual void TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos,
262 UUID fromAgentID, string fromName, ChatTypeEnum type,
263 string message, ChatSourceType src)
264 {
265 // don't send stuff to child agents
266 if (presence.IsChildAgent) return;
267
268 Vector3 fromRegionPos = fromPos + regionPos;
269 Vector3 toRegionPos = presence.AbsolutePosition +
270 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
271 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
272
273 int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos));
274
275 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
276 type == ChatTypeEnum.Say && dis > m_saydistance ||
277 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
278 {
279 return;
280 }
281
282 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
283 presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName,
284 fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully);
285 }
286 }
287}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs
deleted file mode 100644
index ccd81c7..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs
+++ /dev/null
@@ -1,219 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using Nwc.XmlRpc;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38
39namespace OpenSim.Region.Environment.Modules.Avatar.Chat
40{
41 public class IRCBridgeModule : IRegionModule
42 {
43 private static readonly ILog m_log =
44 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 internal static bool configured = false;
47 internal static bool enabled = false;
48 internal static IConfig m_config = null;
49
50 internal static List<ChannelState> m_channels = new List<ChannelState>();
51 internal static List<RegionState> m_regions = new List<RegionState>();
52
53 internal static string password = String.Empty;
54
55 internal RegionState region = null;
56
57 #region IRegionModule Members
58
59 public string Name
60 {
61 get { return "IRCBridgeModule"; }
62 }
63
64 public bool IsSharedModule
65 {
66 get { return false; }
67 }
68
69 public void Initialise(Scene scene, IConfigSource config)
70 {
71 // Do a once-only scan of the configuration file to make
72 // sure it's basically intact.
73
74 if (!configured)
75 {
76 configured = true;
77
78 try
79 {
80 if ((m_config = config.Configs["IRC"]) == null)
81 {
82 m_log.InfoFormat("[IRC-Bridge] module not configured");
83 return;
84 }
85
86 if (!m_config.GetBoolean("enabled", false))
87 {
88 m_log.InfoFormat("[IRC-Bridge] module disabled in configuration");
89 return;
90 }
91 }
92 catch (Exception e)
93 {
94 m_log.ErrorFormat("[IRC-Bridge] configuration failed : {0}", e.Message);
95 return;
96 }
97
98 enabled = true;
99
100 if (config.Configs["RemoteAdmin"] != null)
101 {
102 password = config.Configs["RemoteAdmin"].GetString("access_password", password);
103 scene.CommsManager.HttpServer.AddXmlRPCHandler("irc_admin", XmlRpcAdminMethod, false);
104 }
105 }
106
107 // Iff the IRC bridge is enabled, then each new region may be
108 // connected to IRC. But it should NOT be obligatory (and it
109 // is not).
110 // We have to do ALL of the startup here because PostInitialize
111 // is not called when a region gets created in-flight from the
112 // command line.
113
114 if (enabled)
115 {
116 try
117 {
118 m_log.InfoFormat("[IRC-Bridge] Connecting region {0}", scene.RegionInfo.RegionName);
119 region = new RegionState(scene, m_config);
120 lock (m_regions) m_regions.Add(region);
121 region.Open();
122 }
123 catch (Exception e)
124 {
125 m_log.WarnFormat("[IRC-Bridge] Region {0} not connected to IRC : {1}", scene.RegionInfo.RegionName, e.Message);
126 m_log.Debug(e);
127 }
128 }
129 else
130 {
131 m_log.WarnFormat("[IRC-Bridge] Not enabled. Connect for region {0} ignored", scene.RegionInfo.RegionName);
132 }
133 }
134
135 // This module can be called in-flight in which case PostInitialize
136 // is not called following Initialize. So no use is made of this
137 // call.
138
139 public void PostInitialise()
140 {
141 }
142
143 // Called immediately before the region module is unloaded. Cleanup
144 // the region.
145
146 public void Close()
147 {
148 if (!enabled)
149 return;
150
151 region.Close();
152 lock (m_regions) m_regions.Remove(region);
153 }
154
155 #endregion
156
157 public static XmlRpcResponse XmlRpcAdminMethod(XmlRpcRequest request)
158 {
159 m_log.Info("[IRC-Bridge]: XML RPC Admin Entry");
160
161 XmlRpcResponse response = new XmlRpcResponse();
162 Hashtable responseData = new Hashtable();
163
164 try
165 {
166 Hashtable requestData = (Hashtable)request.Params[0];
167 bool found = false;
168 string region = String.Empty;
169
170 if (password != String.Empty)
171 {
172 if (!requestData.ContainsKey("password"))
173 throw new Exception("Invalid request");
174 if ((string)requestData["password"] != password)
175 throw new Exception("Invalid request");
176 }
177
178 if (!requestData.ContainsKey("region"))
179 throw new Exception("No region name specified");
180 region = (string)requestData["region"];
181
182 foreach (RegionState rs in m_regions)
183 {
184 if (rs.Region == region)
185 {
186 responseData["server"] = rs.cs.Server;
187 responseData["port"] = (int)rs.cs.Port;
188 responseData["user"] = rs.cs.User;
189 responseData["channel"] = rs.cs.IrcChannel;
190 responseData["enabled"] = rs.cs.irc.Enabled;
191 responseData["connected"] = rs.cs.irc.Connected;
192 responseData["nickname"] = rs.cs.irc.Nick;
193 found = true;
194 break;
195 }
196 }
197
198 if (!found) throw new Exception(String.Format("Region <{0}> not found", region));
199
200 responseData["success"] = true;
201 }
202 catch (Exception e)
203 {
204 m_log.InfoFormat("[IRC-Bridge] XML RPC Admin request failed : {0}", e.Message);
205
206 responseData["success"] = "false";
207 responseData["error"] = e.Message;
208 }
209 finally
210 {
211 response.Value = responseData;
212 }
213
214 m_log.Debug("[IRC-Bridge]: XML RPC Admin Exit");
215
216 return response;
217 }
218 }
219}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs
deleted file mode 100644
index c3cafb0..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs
+++ /dev/null
@@ -1,887 +0,0 @@
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 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 */
27
28using System;
29using System.Timers;
30using System.Collections.Generic;
31using System.IO;
32using System.Net.Sockets;
33using System.Reflection;
34using System.Text.RegularExpressions;
35using System.Threading;
36using OpenMetaverse;
37using log4net;
38using Nini.Config;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42
43namespace OpenSim.Region.Environment.Modules.Avatar.Chat
44{
45 public class IRCConnector
46 {
47
48 #region Global (static) state
49
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 // Local constants
53
54 private static readonly Vector3 CenterOfRegion = new Vector3(128, 128, 20);
55 private static readonly char[] CS_SPACE = { ' ' };
56
57 private const int WD_INTERVAL = 1000; // base watchdog interval
58 private static int PING_PERIOD = 15; // WD intervals per PING
59 private static int ICCD_PERIOD = 10; // WD intervals between Connects
60 private static int L_TIMEOUT = 25; // Login time out interval
61
62 private static int _idk_ = 0; // core connector identifier
63 private static int _pdk_ = 0; // ping interval counter
64 private static int _icc_ = 0; // IRC connect counter
65
66 // List of configured connectors
67
68 private static List<IRCConnector> m_connectors = new List<IRCConnector>();
69
70 // Watchdog state
71
72 private static System.Timers.Timer m_watchdog = null;
73
74 static IRCConnector()
75 {
76 m_log.DebugFormat("[IRC-Connector]: Static initialization started");
77 m_watchdog = new System.Timers.Timer(WD_INTERVAL);
78 m_watchdog.Elapsed += new ElapsedEventHandler(WatchdogHandler);
79 m_watchdog.AutoReset = true;
80 m_watchdog.Start();
81 m_log.DebugFormat("[IRC-Connector]: Static initialization complete");
82 }
83
84 #endregion
85
86 #region Instance state
87
88 // Connector identity
89
90 internal int idn = _idk_++;
91
92 // How many regions depend upon this connection
93 // This count is updated by the ChannelState object and reflects the sum
94 // of the region clients associated with the set of associated channel
95 // state instances. That's why it cannot be managed here.
96
97 internal int depends = 0;
98
99 // Working threads
100
101 private Thread m_listener = null;
102
103 private Object msyncConnect = new Object();
104
105 internal bool m_randomizeNick = true; // add random suffix
106 internal string m_baseNick = null; // base name for randomizing
107 internal string m_nick = null; // effective nickname
108
109 public string Nick // Public property
110 {
111 get { return m_nick; }
112 set { m_nick = value; }
113 }
114
115 private bool m_enabled = false; // connector enablement
116 public bool Enabled
117 {
118 get { return m_enabled; }
119 }
120
121 private bool m_connected = false; // connection status
122 private bool m_pending = false; // login disposition
123 private int m_timeout = L_TIMEOUT; // login timeout counter
124 public bool Connected
125 {
126 get { return m_connected; }
127 }
128
129 private string m_ircChannel; // associated channel id
130 public string IrcChannel
131 {
132 get { return m_ircChannel; }
133 set { m_ircChannel = value; }
134 }
135
136 private uint m_port = 6667; // session port
137 public uint Port
138 {
139 get { return m_port; }
140 set { m_port = value; }
141 }
142
143 private string m_server = null; // IRC server name
144 public string Server
145 {
146 get { return m_server; }
147 set { m_server = value; }
148 }
149 private string m_password = null;
150 public string Password
151 {
152 get { return m_password; }
153 set { m_password = value; }
154 }
155
156 private string m_user = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot";
157 public string User
158 {
159 get { return m_user; }
160 }
161
162 // Network interface
163
164 private TcpClient m_tcp;
165 private NetworkStream m_stream = null;
166 private StreamReader m_reader;
167 private StreamWriter m_writer;
168
169 // Channel characteristic info (if available)
170
171 internal string usermod = String.Empty;
172 internal string chanmod = String.Empty;
173 internal string version = String.Empty;
174 internal bool motd = false;
175
176 #endregion
177
178 #region connector instance management
179
180 internal IRCConnector(ChannelState cs)
181 {
182
183 // Prepare network interface
184
185 m_tcp = null;
186 m_writer = null;
187 m_reader = null;
188
189 // Setup IRC session parameters
190
191 m_server = cs.Server;
192 m_password = cs.Password;
193 m_baseNick = cs.BaseNickname;
194 m_randomizeNick = cs.RandomizeNickname;
195 m_ircChannel = cs.IrcChannel;
196 m_port = cs.Port;
197 m_user = cs.User;
198
199 if (m_watchdog == null)
200 {
201 // Non-differentiating
202
203 ICCD_PERIOD = cs.ConnectDelay;
204 PING_PERIOD = cs.PingDelay;
205
206 // Smaller values are not reasonable
207
208 if (ICCD_PERIOD < 5)
209 ICCD_PERIOD = 5;
210
211 if (PING_PERIOD < 5)
212 PING_PERIOD = 5;
213
214 _icc_ = ICCD_PERIOD; // get started right away!
215
216 }
217
218 // The last line of defense
219
220 if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null)
221 throw new Exception("Invalid connector configuration");
222
223 // Generate an initial nickname if randomizing is enabled
224
225 if (m_randomizeNick)
226 {
227 m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
228 }
229
230 // Add the newly created connector to the known connectors list
231
232 m_connectors.Add(this);
233
234 m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn);
235
236 }
237
238 ~IRCConnector()
239 {
240 m_watchdog.Stop();
241 Close();
242 }
243
244 // Mark the connector as connectable. Harmless if already enabled.
245
246 public void Open()
247 {
248 if (!m_enabled)
249 {
250
251 m_connectors.Add(this);
252 m_enabled = true;
253
254 if (!Connected)
255 {
256 Connect();
257 }
258
259 }
260 }
261
262 // Only close the connector if the dependency count is zero.
263
264 public void Close()
265 {
266
267 m_log.InfoFormat("[IRC-Connector-{0}] Closing", idn);
268
269 lock (msyncConnect)
270 {
271
272 if ((depends == 0) && Enabled)
273 {
274
275 m_enabled = false;
276
277 if (Connected)
278 {
279 m_log.DebugFormat("[IRC-Connector-{0}] Closing interface", idn);
280
281 // Cleanup the IRC session
282
283 try
284 {
285 m_writer.WriteLine(String.Format("QUIT :{0} to {1} wormhole to {2} closing",
286 m_nick, m_ircChannel, m_server));
287 m_writer.Flush();
288 }
289 catch (Exception) {}
290
291
292 m_connected = false;
293
294 try { m_writer.Close(); } catch (Exception) {}
295 try { m_reader.Close(); } catch (Exception) {}
296 try { m_stream.Close(); } catch (Exception) {}
297 try { m_tcp.Close(); } catch (Exception) {}
298
299 }
300
301 m_connectors.Remove(this);
302
303 }
304 }
305
306 m_log.InfoFormat("[IRC-Connector-{0}] Closed", idn);
307
308 }
309
310 #endregion
311
312 #region session management
313
314 // Connect to the IRC server. A connector should always be connected, once enabled
315
316 public void Connect()
317 {
318
319 if (!m_enabled)
320 return;
321
322 // Delay until next WD cycle if this is too close to the last start attempt
323
324 while (_icc_ < ICCD_PERIOD)
325 return;
326
327 m_log.DebugFormat("[IRC-Connector-{0}]: Connection request for {1} on {2}:{3}", idn, m_nick, m_server, m_ircChannel);
328
329 lock (msyncConnect)
330 {
331
332 _icc_ = 0;
333
334 try
335 {
336 if (m_connected) return;
337
338 m_connected = true;
339 m_pending = true;
340 m_timeout = L_TIMEOUT;
341
342 m_tcp = new TcpClient(m_server, (int)m_port);
343 m_stream = m_tcp.GetStream();
344 m_reader = new StreamReader(m_stream);
345 m_writer = new StreamWriter(m_stream);
346
347 m_log.InfoFormat("[IRC-Connector-{0}]: Connected to {1}:{2}", idn, m_server, m_port);
348
349 m_listener = new Thread(new ThreadStart(ListenerRun));
350 m_listener.Name = "IRCConnectorListenerThread";
351 m_listener.IsBackground = true;
352 m_listener.Start();
353 ThreadTracker.Add(m_listener);
354
355 // This is the message order recommended by RFC 2812
356 if (m_password != null)
357 m_writer.WriteLine(String.Format("PASS {0}", m_password));
358 m_writer.WriteLine(String.Format("NICK {0}", m_nick));
359 m_writer.Flush();
360 m_writer.WriteLine(m_user);
361 m_writer.Flush();
362 m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel));
363 m_writer.Flush();
364
365 m_log.InfoFormat("[IRC-Connector-{0}]: {1} has asked to join {2}", idn, m_nick, m_ircChannel);
366
367 }
368 catch (Exception e)
369 {
370 m_log.ErrorFormat("[IRC-Connector-{0}] cannot connect {1} to {2}:{3}: {4}",
371 idn, m_nick, m_server, m_port, e.Message);
372 m_connected = false;
373 m_pending = false;
374 }
375
376 }
377
378 return;
379
380 }
381
382 // Reconnect is used to force a re-cycle of the IRC connection. Should generally
383 // be a transparent event
384
385 public void Reconnect()
386 {
387 m_log.DebugFormat("[IRC-Connector-{0}]: Reconnect request for {1} on {2}:{3}", idn, m_nick, m_server, m_ircChannel);
388
389 // Don't do this if a Connect is in progress...
390
391 lock (msyncConnect)
392 {
393
394 if (m_connected)
395 {
396 m_log.InfoFormat("[IRC-Connector-{0}] Resetting connector", idn);
397
398 // Mark as disconnected. This will allow the listener thread
399 // to exit if still in-flight.
400
401
402 // The listener thread is not aborted - it *might* actually be
403 // the thread that is running the Reconnect! Instead just close
404 // the socket and it will disappear of its own accord, once this
405 // processing is completed.
406
407 try { m_writer.Close(); } catch (Exception) {}
408 try { m_reader.Close(); } catch (Exception) {}
409 try { m_tcp.Close(); } catch (Exception) {}
410
411 m_connected = false;
412 m_pending = false;
413
414 }
415
416 }
417
418 Connect();
419
420 }
421
422 #endregion
423
424 #region Outbound (to-IRC) message handlers
425
426 public void PrivMsg(string pattern, string from, string region, string msg)
427 {
428
429 m_log.DebugFormat("[IRC-Connector-{0}] PrivMsg to IRC from {1}: <{2}>", idn, from,
430 String.Format(pattern, m_ircChannel, from, region, msg));
431
432 // One message to the IRC server
433
434 try
435 {
436 m_writer.WriteLine(pattern, m_ircChannel, from, region, msg);
437 m_writer.Flush();
438 m_log.DebugFormat("[IRC-Connector-{0}]: PrivMsg from {1} in {2}: {3}", idn, from, region, msg);
439 }
440 catch (IOException)
441 {
442 m_log.ErrorFormat("[IRC-Connector-{0}]: PrivMsg I/O Error: disconnected from IRC server", idn);
443 Reconnect();
444 }
445 catch (Exception ex)
446 {
447 m_log.ErrorFormat("[IRC-Connector-{0}]: PrivMsg exception : {1}", idn, ex.Message);
448 m_log.Debug(ex);
449 }
450
451 }
452
453 public void Send(string msg)
454 {
455
456 m_log.DebugFormat("[IRC-Connector-{0}] Send to IRC : <{1}>", idn, msg);
457
458 try
459 {
460 m_writer.WriteLine(msg);
461 m_writer.Flush();
462 m_log.DebugFormat("[IRC-Connector-{0}] Sent command string: {1}", idn, msg);
463 }
464 catch (IOException)
465 {
466 m_log.ErrorFormat("[IRC-Connector-{0}] Disconnected from IRC server.(Send)", idn);
467 Reconnect();
468 }
469 catch (Exception ex)
470 {
471 m_log.ErrorFormat("[IRC-Connector-{0}] Send exception trap: {0}", idn, ex.Message);
472 m_log.Debug(ex);
473 }
474
475 }
476
477 #endregion
478
479 public void ListenerRun()
480 {
481 string inputLine;
482
483 try
484 {
485 while (m_enabled && m_connected)
486 {
487
488 if ((inputLine = m_reader.ReadLine()) == null)
489 throw new Exception("Listener input socket closed");
490
491 // m_log.Info("[IRCConnector]: " + inputLine);
492
493 if (inputLine.Contains("PRIVMSG"))
494 {
495
496 Dictionary<string, string> data = ExtractMsg(inputLine);
497
498 // Any chat ???
499 if (data != null)
500 {
501
502 OSChatMessage c = new OSChatMessage();
503 c.Message = data["msg"];
504 c.Type = ChatTypeEnum.Region;
505 c.Position = CenterOfRegion;
506 c.From = data["nick"];
507 c.Sender = null;
508 c.SenderUUID = UUID.Zero;
509
510 // Is message "\001ACTION foo bar\001"?
511 // Then change to: "/me foo bar"
512
513 if ((1 == c.Message[0]) && c.Message.Substring(1).StartsWith("ACTION"))
514 c.Message = String.Format("/me {0}", c.Message.Substring(8, c.Message.Length - 9));
515
516 ChannelState.OSChat(this, c, false);
517
518 }
519
520 }
521 else
522 {
523 ProcessIRCCommand(inputLine);
524 }
525 }
526 }
527 catch (Exception /*e*/)
528 {
529 // m_log.ErrorFormat("[IRC-Connector-{0}]: ListenerRun exception trap: {1}", idn, e.Message);
530 // m_log.Debug(e);
531 }
532
533 // This is potentially circular, but harmless if so.
534 // The connection is marked as not connected the first time
535 // through reconnect.
536
537 if (m_enabled) Reconnect();
538
539 }
540
541 private Regex RE = new Regex(@":(?<nick>[\w-]*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)",
542 RegexOptions.Multiline);
543
544 private Dictionary<string, string> ExtractMsg(string input)
545 {
546 //examines IRC commands and extracts any private messages
547 // which will then be reboadcast in the Sim
548
549 // m_log.InfoFormat("[IRC-Connector-{0}]: ExtractMsg: {1}", idn, input);
550
551 Dictionary<string, string> result = null;
552 MatchCollection matches = RE.Matches(input);
553
554 // Get some direct matches $1 $4 is a
555 if ((matches.Count == 0) || (matches.Count != 1) || (matches[0].Groups.Count != 5))
556 {
557 // m_log.Info("[IRCConnector]: Number of matches: " + matches.Count);
558 // if (matches.Count > 0)
559 // {
560 // m_log.Info("[IRCConnector]: Number of groups: " + matches[0].Groups.Count);
561 // }
562 return null;
563 }
564
565 result = new Dictionary<string, string>();
566 result.Add("nick", matches[0].Groups[1].Value);
567 result.Add("user", matches[0].Groups[2].Value);
568 result.Add("channel", matches[0].Groups[3].Value);
569 result.Add("msg", matches[0].Groups[4].Value);
570
571 return result;
572 }
573
574 public void BroadcastSim(string sender, string format, params string[] args)
575 {
576 try
577 {
578 OSChatMessage c = new OSChatMessage();
579 c.From = sender;
580 c.Message = String.Format(format, args);
581 c.Type = ChatTypeEnum.Region; // ChatTypeEnum.Say;
582 c.Position = CenterOfRegion;
583 c.Sender = null;
584 c.SenderUUID = UUID.Zero;
585
586 ChannelState.OSChat(this, c, true);
587
588 }
589 catch (Exception ex) // IRC gate should not crash Sim
590 {
591 m_log.ErrorFormat("[IRC-Connector-{0}]: BroadcastSim Exception Trap: {1}\n{2}", idn, ex.Message, ex.StackTrace);
592 }
593 }
594
595 #region IRC Command Handlers
596
597 public void ProcessIRCCommand(string command)
598 {
599
600 string[] commArgs;
601 string c_server = m_server;
602
603 string pfx = String.Empty;
604 string cmd = String.Empty;
605 string parms = String.Empty;
606
607 // ":" indicates that a prefix is present
608 // There are NEVER more than 17 real
609 // fields. A parameter that starts with
610 // ":" indicates that the remainder of the
611 // line is a single parameter value.
612
613 commArgs = command.Split(CS_SPACE,2);
614
615 if (commArgs[0].StartsWith(":"))
616 {
617 pfx = commArgs[0].Substring(1);
618 commArgs = commArgs[1].Split(CS_SPACE,2);
619 }
620
621 cmd = commArgs[0];
622 parms = commArgs[1];
623
624 // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}>", idn, pfx, cmd);
625
626 switch (cmd)
627 {
628
629 // Messages 001-004 are always sent
630 // following signon.
631
632 case "001" : // Welcome ...
633 case "002" : // Server information
634 case "003" : // Welcome ...
635 break;
636 case "004" : // Server information
637 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
638 commArgs = parms.Split(CS_SPACE);
639 c_server = commArgs[1];
640 m_server = c_server;
641 version = commArgs[2];
642 usermod = commArgs[3];
643 chanmod = commArgs[4];
644 break;
645 case "005" : // Server information
646 break;
647 case "042" :
648 case "250" :
649 case "251" :
650 case "252" :
651 case "254" :
652 case "255" :
653 case "265" :
654 case "266" :
655 case "332" : // Subject
656 case "333" : // Subject owner (?)
657 case "353" : // Name list
658 case "366" : // End-of-Name list marker
659 case "372" : // MOTD body
660 case "375" : // MOTD start
661 m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
662 break;
663 case "376" : // MOTD end
664 m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
665 motd = true;
666 break;
667 case "451" : // Not registered
668 break;
669 case "433" : // Nickname in use
670 // Gen a new name
671 m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
672 m_log.ErrorFormat("[IRC-Connector-{0}]: [{1}] IRC SERVER reports NicknameInUse, trying {2}", idn, cmd, m_nick);
673 // Retry
674 m_writer.WriteLine(String.Format("NICK {0}", m_nick));
675 m_writer.Flush();
676 m_writer.WriteLine(m_user);
677 m_writer.Flush();
678 m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel));
679 m_writer.Flush();
680 break;
681 case "479" : // Bad channel name, etc. This will never work, so disable the connection
682 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
683 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] Connector disabled", idn, cmd);
684 m_enabled = false;
685 m_connected = false;
686 m_pending = false;
687 break;
688 case "NOTICE" :
689 m_log.WarnFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
690 break;
691 case "ERROR" :
692 m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
693 if (parms.Contains("reconnect too fast"))
694 ICCD_PERIOD++;
695 m_pending = false;
696 Reconnect();
697 break;
698 case "PING" :
699 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
700 m_writer.WriteLine(String.Format("PONG {0}", parms));
701 m_writer.Flush();
702 break;
703 case "PONG" :
704 break;
705 case "JOIN":
706 if (m_pending)
707 {
708 m_log.InfoFormat("[IRC-Connector-{0}] [{1}] Connected", idn, cmd);
709 m_pending = false;
710 }
711 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
712 eventIrcJoin(pfx, cmd, parms);
713 break;
714 case "PART":
715 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
716 eventIrcPart(pfx, cmd, parms);
717 break;
718 case "MODE":
719 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
720 eventIrcMode(pfx, cmd, parms);
721 break;
722 case "NICK":
723 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
724 eventIrcNickChange(pfx, cmd, parms);
725 break;
726 case "KICK":
727 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
728 eventIrcKick(pfx, cmd, parms);
729 break;
730 case "QUIT":
731 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
732 eventIrcQuit(pfx, cmd, parms);
733 break;
734 default :
735 m_log.DebugFormat("[IRC-Connector-{0}] Command '{1}' ignored, parms = {2}", idn, cmd, parms);
736 break;
737 }
738
739 // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}> complete", idn, pfx, cmd);
740
741 }
742
743 public void eventIrcJoin(string prefix, string command, string parms)
744 {
745 string[] args = parms.Split(CS_SPACE,2);
746 string IrcUser = prefix.Split('!')[0];
747 string IrcChannel = args[0];
748
749 if (IrcChannel.StartsWith(":"))
750 IrcChannel = IrcChannel.Substring(1);
751
752 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCJoin {1}:{2}", idn, m_server, m_ircChannel);
753 BroadcastSim(IrcUser, "/me joins {0}", IrcChannel);
754 }
755
756 public void eventIrcPart(string prefix, string command, string parms)
757 {
758 string[] args = parms.Split(CS_SPACE,2);
759 string IrcUser = prefix.Split('!')[0];
760 string IrcChannel = args[0];
761
762 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCPart {1}:{2}", idn, m_server, m_ircChannel);
763 BroadcastSim(IrcUser, "/me parts {0}", IrcChannel);
764 }
765
766 public void eventIrcMode(string prefix, string command, string parms)
767 {
768 string[] args = parms.Split(CS_SPACE,2);
769 string UserMode = args[1];
770
771 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCMode {1}:{2}", idn, m_server, m_ircChannel);
772 if (UserMode.Substring(0, 1) == ":")
773 {
774 UserMode = UserMode.Remove(0, 1);
775 }
776 }
777
778 public void eventIrcNickChange(string prefix, string command, string parms)
779 {
780 string[] args = parms.Split(CS_SPACE,2);
781 string UserOldNick = prefix.Split('!')[0];
782 string UserNewNick = args[0].Remove(0, 1);
783
784 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCNickChange {1}:{2}", idn, m_server, m_ircChannel);
785 BroadcastSim(UserOldNick, "/me is now known as {0}", UserNewNick);
786 }
787
788 public void eventIrcKick(string prefix, string command, string parms)
789 {
790 string[] args = parms.Split(CS_SPACE,3);
791 string UserKicker = prefix.Split('!')[0];
792 string IrcChannel = args[0];
793 string UserKicked = args[1];
794 string KickMessage = args[2];
795
796 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCKick {1}:{2}", idn, m_server, m_ircChannel);
797 BroadcastSim(UserKicker, "/me kicks kicks {0} off {1} saying \"{2}\"", UserKicked, IrcChannel, KickMessage);
798
799 if (UserKicked == m_nick)
800 {
801 BroadcastSim(m_nick, "Hey, that was me!!!");
802 }
803
804 }
805
806 public void eventIrcQuit(string prefix, string command, string parms)
807 {
808 string IrcUser = prefix.Split('!')[0];
809 string QuitMessage = parms;
810
811 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCQuit {1}:{2}", idn, m_server, m_ircChannel);
812 BroadcastSim(IrcUser, "/me quits saying \"{0}\"", QuitMessage);
813 }
814
815 #endregion
816
817 #region Connector Watch Dog
818
819 // A single watch dog monitors extant connectors and makes sure that they
820 // are re-connected as necessary. If a connector IS connected, then it is
821 // pinged, but only if a PING period has elapsed.
822
823 protected static void WatchdogHandler(Object source, ElapsedEventArgs args)
824 {
825
826 // m_log.InfoFormat("[IRC-Watchdog] Status scan");
827
828 _pdk_ = (_pdk_+1)%PING_PERIOD; // cycle the ping trigger
829 _icc_++; // increment the inter-consecutive-connect-delay counter
830
831 foreach (IRCConnector connector in m_connectors)
832 {
833 if (connector.Enabled)
834 {
835 if (!connector.Connected)
836 {
837 try
838 {
839 // m_log.DebugFormat("[IRC-Watchdog] Connecting {1}:{2}", connector.idn, connector.m_server, connector.m_ircChannel);
840 connector.Connect();
841 }
842 catch (Exception e)
843 {
844 m_log.ErrorFormat("[IRC-Watchdog] Exception on connector {0}: {1} ", connector.idn, e.Message);
845 }
846 }
847 else
848 {
849
850 if (connector.m_pending)
851 {
852 if (connector.m_timeout == 0)
853 {
854 m_log.ErrorFormat("[IRC-Watchdog] Login timed-out for connector {0}, reconnecting", connector.idn);
855 connector.Reconnect();
856 }
857 else
858 connector.m_timeout--;
859 }
860
861 if (_pdk_ == 0)
862 {
863 try
864 {
865 connector.m_writer.WriteLine(String.Format("PING :{0}", connector.m_server));
866 connector.m_writer.Flush();
867 }
868 catch (Exception /*e*/)
869 {
870 // m_log.ErrorFormat("[IRC-PingRun] Exception on connector {0}: {1} ", connector.idn, e.Message);
871 // m_log.Debug(e);
872 connector.Reconnect();
873 }
874 }
875
876 }
877 }
878 }
879
880 // m_log.InfoFormat("[IRC-Watchdog] Status scan completed");
881
882 }
883
884 #endregion
885
886 }
887}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs
deleted file mode 100644
index 78f4265..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs
+++ /dev/null
@@ -1,424 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text.RegularExpressions;
32using log4net;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38namespace OpenSim.Region.Environment.Modules.Avatar.Chat
39{
40 // An instance of this class exists for every active region
41
42 internal class RegionState
43 {
44
45 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(128, 128, 20);
49 private const int DEBUG_CHANNEL = 2147483647;
50
51 private static int _idk_ = 0;
52
53 // Runtime variables; these values are assigned when the
54 // IrcState is created and remain constant thereafter.
55
56 internal string Region = String.Empty;
57 internal string Host = String.Empty;
58 internal string LocX = String.Empty;
59 internal string LocY = String.Empty;
60 internal string MA1 = String.Empty;
61 internal string MA2 = String.Empty;
62 internal string IDK = String.Empty;
63
64 // System values - used only be the IRC classes themselves
65
66 internal ChannelState cs = null; // associated IRC configuration
67 internal Scene scene = null; // associated scene
68 internal IConfig config = null; // configuration file reference
69 internal bool enabled = true;
70
71 // This list is used to keep track of who is here, and by
72 // implication, who is not.
73
74 internal List<IClientAPI> clients = new List<IClientAPI>();
75
76 // Setup runtime variable values
77
78 public RegionState(Scene p_scene, IConfig p_config)
79 {
80
81 scene = p_scene;
82 config = p_config;
83
84 Region = scene.RegionInfo.RegionName;
85 Host = scene.RegionInfo.ExternalHostName;
86 LocX = Convert.ToString(scene.RegionInfo.RegionLocX);
87 LocY = Convert.ToString(scene.RegionInfo.RegionLocY);
88 MA1 = scene.RegionInfo.MasterAvatarFirstName;
89 MA2 = scene.RegionInfo.MasterAvatarLastName;
90 IDK = Convert.ToString(_idk_++);
91
92 // OpenChannel conditionally establishes a connection to the
93 // IRC server. The request will either succeed, or it will
94 // throw an exception.
95
96 ChannelState.OpenChannel(this, config);
97
98 // Connect channel to world events
99
100 scene.EventManager.OnChatFromWorld += OnSimChat;
101 scene.EventManager.OnChatFromClient += OnSimChat;
102 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
103 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
104
105 m_log.InfoFormat("[IRC-Region {0}] Initialization complete", Region);
106
107 }
108
109 // Auto cleanup when abandoned
110
111 ~RegionState()
112 {
113 if (cs != null)
114 cs.RemoveRegion(this);
115 }
116
117 // Called by PostInitialize after all regions have been created
118
119 public void Open()
120 {
121 cs.Open(this);
122 enabled = true;
123 }
124
125 // Called by IRCBridgeModule.Close immediately prior to unload
126 // of the module for this region. This happens when the region
127 // is being removed or the server is terminating. The IRC
128 // BridgeModule will remove the region from the region list
129 // when control returns.
130
131 public void Close()
132 {
133 enabled = false;
134 cs.Close(this);
135 }
136
137 // The agent has disconnected, cleanup associated resources
138
139 private void OnClientLoggedOut(IClientAPI client)
140 {
141 try
142 {
143 if (clients.Contains(client))
144 {
145 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting))
146 {
147 m_log.InfoFormat("[IRC-Region {0}]: {1} has left", Region, client.Name);
148 cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", client.Name));
149 }
150 client.OnLogout -= OnClientLoggedOut;
151 client.OnConnectionClosed -= OnClientLoggedOut;
152 clients.Remove(client);
153 }
154 }
155 catch (Exception ex)
156 {
157 m_log.ErrorFormat("[IRC-Region {0}]: ClientLoggedOut exception: {1}", Region, ex.Message);
158 m_log.Debug(ex);
159 }
160 }
161
162 // This event indicates that the agent has left the building. We should treat that the same
163 // as if the agent has logged out (we don't want cross-region noise - or do we?)
164
165 private void OnMakeChildAgent(ScenePresence presence)
166 {
167
168 IClientAPI client = presence.ControllingClient;
169
170 try
171 {
172 if (clients.Contains(client))
173 {
174 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting))
175 {
176 string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname);
177 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));
179 }
180 client.OnLogout -= OnClientLoggedOut;
181 client.OnConnectionClosed -= OnClientLoggedOut;
182 clients.Remove(client);
183 }
184 }
185 catch (Exception ex)
186 {
187 m_log.ErrorFormat("[IRC-Region {0}]: MakeChildAgent exception: {1}", Region, ex.Message);
188 m_log.Debug(ex);
189 }
190
191 }
192
193 // An agent has entered the region (from another region). Add the client to the locally
194 // known clients list
195
196 private void OnMakeRootAgent(ScenePresence presence)
197 {
198
199 IClientAPI client = presence.ControllingClient;
200
201 try
202 {
203 if (!clients.Contains(client))
204 {
205 client.OnLogout += OnClientLoggedOut;
206 client.OnConnectionClosed += OnClientLoggedOut;
207 clients.Add(client);
208 if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting))
209 {
210 string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname);
211 m_log.DebugFormat("[IRC-Region {0}] {1} has arrived", Region, clientName);
212 cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has arrived", clientName));
213 }
214 }
215 }
216 catch (Exception ex)
217 {
218 m_log.ErrorFormat("[IRC-Region {0}]: MakeRootAgent exception: {1}", Region, ex.Message);
219 m_log.Debug(ex);
220 }
221
222 }
223
224 // This handler detects chat events int he virtual world.
225
226 public void OnSimChat(Object sender, OSChatMessage msg)
227 {
228
229 // early return if this comes from the IRC forwarder
230
231 if (cs.irc.Equals(sender)) return;
232
233 // early return if nothing to forward
234
235 if (msg.Message.Length == 0) return;
236
237 // check for commands coming from avatars or in-world
238 // object (if commands are enabled)
239
240 if (cs.CommandsEnabled && msg.Channel == cs.CommandChannel)
241 {
242
243 m_log.DebugFormat("[IRC-Region {0}] command on channel {1}: {2}", Region, msg.Channel, msg.Message);
244
245 string[] messages = msg.Message.Split(' ');
246 string command = messages[0].ToLower();
247
248 try
249 {
250 switch (command)
251 {
252
253 // These commands potentially require a change in the
254 // underlying ChannelState.
255
256 case "server":
257 cs.Close(this);
258 cs = cs.UpdateServer(this, messages[1]);
259 cs.Open(this);
260 break;
261 case "port":
262 cs.Close(this);
263 cs = cs.UpdatePort(this, messages[1]);
264 cs.Open(this);
265 break;
266 case "channel":
267 cs.Close(this);
268 cs = cs.UpdateChannel(this, messages[1]);
269 cs.Open(this);
270 break;
271 case "nick":
272 cs.Close(this);
273 cs = cs.UpdateNickname(this, messages[1]);
274 cs.Open(this);
275 break;
276
277 // These may also (but are less likely) to require a
278 // change in ChannelState.
279
280 case "client-reporting":
281 cs = cs.UpdateClientReporting(this, messages[1]);
282 break;
283 case "in-channel":
284 cs = cs.UpdateRelayIn(this, messages[1]);
285 break;
286 case "out-channel":
287 cs = cs.UpdateRelayOut(this, messages[1]);
288 break;
289
290 // These are all taken to be temporary changes in state
291 // so the underlying connector remains intact. But note
292 // that with regions sharing a connector, there could
293 // be interference.
294
295 case "close":
296 enabled = false;
297 cs.Close(this);
298 break;
299
300 case "connect":
301 enabled = true;
302 cs.Open(this);
303 break;
304
305 case "reconnect":
306 enabled = true;
307 cs.Close(this);
308 cs.Open(this);
309 break;
310
311 // This one is harmless as far as we can judge from here.
312 // If it is not, then the complaints will eventually make
313 // that evident.
314
315 default:
316 m_log.DebugFormat("[IRC-Region {0}] Forwarding unrecognized command to IRC : {1}",
317 Region, msg.Message);
318 cs.irc.Send(msg.Message);
319 break;
320 }
321 }
322 catch (Exception ex)
323 {
324 m_log.WarnFormat("[IRC-Region {0}] error processing in-world command channel input: {1}",
325 Region, ex.Message);
326 m_log.Debug(ex);
327 }
328
329 return;
330
331 }
332
333 // The command channel remains enabled, even if we have otherwise disabled the IRC
334 // interface.
335
336 if (!enabled)
337 return;
338
339 // drop messages unless they are on a valid in-world
340 // channel as configured in the ChannelState
341
342 if (!cs.ValidInWorldChannels.Contains(msg.Channel))
343 {
344 m_log.DebugFormat("[IRC-Region {0}] dropping message {1} on channel {2}", Region, msg, msg.Channel);
345 return;
346 }
347
348 ScenePresence avatar = null;
349 string fromName = msg.From;
350
351 if (msg.Sender != null)
352 {
353 avatar = scene.GetScenePresence(msg.Sender.AgentId);
354 if (avatar != null) fromName = avatar.Name;
355 }
356
357 if (!cs.irc.Connected)
358 {
359 m_log.WarnFormat("[IRC-Region {0}] IRCConnector not connected: dropping message from {1}", Region, fromName);
360 return;
361 }
362
363 m_log.DebugFormat("[IRC-Region {0}] heard on channel {1} : {2}", Region, msg.Channel, msg.Message);
364
365 if (null != avatar && cs.RelayChat && (msg.Channel == 0 || msg.Channel == DEBUG_CHANNEL))
366 {
367 string txt = msg.Message;
368 if (txt.StartsWith("/me "))
369 txt = String.Format("{0} {1}", fromName, msg.Message.Substring(4));
370
371 cs.irc.PrivMsg(cs.PrivateMessageFormat, fromName, Region, txt);
372 return;
373 }
374
375 if (null == avatar && cs.RelayPrivateChannels && null != cs.AccessPassword &&
376 msg.Channel == cs.RelayChannelOut)
377 {
378 Match m = cs.AccessPasswordRegex.Match(msg.Message);
379 if (null != m)
380 {
381 m_log.DebugFormat("[IRC] relaying message from {0}: {1}", m.Groups["avatar"].ToString(),
382 m.Groups["message"].ToString());
383 cs.irc.PrivMsg(cs.PrivateMessageFormat, m.Groups["avatar"].ToString(),
384 scene.RegionInfo.RegionName, m.Groups["message"].ToString());
385 }
386 }
387 }
388
389 // This method gives the region an opportunity to interfere with
390 // message delivery. For now we just enforce the enable/disable
391 // flag.
392
393 internal void OSChat(Object irc, OSChatMessage msg)
394 {
395 if (enabled)
396 {
397 // m_log.DebugFormat("[IRC-OSCHAT] Region {0} being sent message", region.Region);
398 msg.Scene = scene;
399 scene.EventManager.TriggerOnChatBroadcast(irc, msg);
400 }
401 }
402
403 // This supports any local message traffic that might be needed in
404 // support of command processing. At present there is none.
405
406 internal void LocalChat(string msg)
407 {
408 if (enabled)
409 {
410 OSChatMessage osm = new OSChatMessage();
411 osm.From = "IRC Agent";
412 osm.Message = msg;
413 osm.Type = ChatTypeEnum.Region;
414 osm.Position = CenterOfRegion;
415 osm.Sender = null;
416 osm.SenderUUID = OpenMetaverse.UUID.Zero; // Hmph! Still?
417 osm.Channel = 0;
418 OSChat(this, osm);
419 }
420 }
421
422 }
423
424}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Combat/CombatModule.cs
deleted file mode 100644
index f032319..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Combat/CombatModule.cs
+++ /dev/null
@@ -1,154 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Net.Sockets;
33using System.Reflection;
34using System.Xml;
35using OpenMetaverse;
36using log4net;
37using Nini.Config;
38using Nwc.XmlRpc;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Framework.Communications.Cache;
43
44namespace OpenSim.Region.Environment.Modules.Avatar.Combat.CombatModule
45{
46 public class CombatModule : IRegionModule
47 {
48 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 /// <summary>
51 /// Region UUIDS indexed by AgentID
52 /// </summary>
53 //private Dictionary<UUID, UUID> m_rootAgents = new Dictionary<UUID, UUID>();
54
55 /// <summary>
56 /// Scenes by Region Handle
57 /// </summary>
58 private Dictionary<ulong, Scene> m_scenel = new Dictionary<ulong, Scene>();
59
60 /// <summary>
61 /// Startup
62 /// </summary>
63 /// <param name="scene"></param>
64 /// <param name="config"></param>
65 public void Initialise(Scene scene, IConfigSource config)
66 {
67 lock (m_scenel)
68 {
69 if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle))
70 {
71 m_scenel[scene.RegionInfo.RegionHandle] = scene;
72 }
73 else
74 {
75 m_scenel.Add(scene.RegionInfo.RegionHandle, scene);
76 }
77 }
78
79 scene.EventManager.OnAvatarKilled += KillAvatar;
80 }
81
82 public void PostInitialise()
83 {
84 }
85
86 public void Close()
87 {
88 }
89
90 public string Name
91 {
92 get { return "CombatModule"; }
93 }
94
95 public bool IsSharedModule
96 {
97 get { return true; }
98 }
99
100 private void KillAvatar(uint killerObjectLocalID, ScenePresence DeadAvatar)
101 {
102 if (killerObjectLocalID == 0)
103 DeadAvatar.ControllingClient.SendAgentAlertMessage("You committed suicide!", true);
104 else
105 {
106 bool foundResult = false;
107 string resultstring = "";
108 List<ScenePresence> allav = DeadAvatar.Scene.GetScenePresences();
109 try
110 {
111 foreach (ScenePresence av in allav)
112 {
113 if (av.LocalId == killerObjectLocalID)
114 {
115 av.ControllingClient.SendAlertMessage("You fragged " + DeadAvatar.Firstname + " " + DeadAvatar.Lastname);
116 resultstring = av.Firstname + " " + av.Lastname;
117 foundResult = true;
118 }
119 }
120 } catch (System.InvalidOperationException)
121 {
122
123 }
124
125 if (!foundResult)
126 {
127 SceneObjectPart part = DeadAvatar.Scene.GetSceneObjectPart(killerObjectLocalID);
128 if (part != null)
129 {
130 ScenePresence av = DeadAvatar.Scene.GetScenePresence(part.OwnerID);
131 if (av != null)
132 {
133 av.ControllingClient.SendAlertMessage("You fragged " + DeadAvatar.Firstname + " " + DeadAvatar.Lastname);
134 resultstring = av.Firstname + " " + av.Lastname;
135 DeadAvatar.ControllingClient.SendAgentAlertMessage("You got killed by " + resultstring + "!", true);
136 }
137 else
138 {
139 string killer = DeadAvatar.Scene.CommsManager.UUIDNameRequestString(part.OwnerID);
140 DeadAvatar.ControllingClient.SendAgentAlertMessage("You impaled yourself on " + part.Name + " owned by " + killer +"!", true);
141 }
142 //DeadAvatar.Scene. part.ObjectOwner
143 }
144 else
145 {
146 DeadAvatar.ControllingClient.SendAgentAlertMessage("You died!", true);
147 }
148 }
149 }
150 DeadAvatar.Health = 100;
151 DeadAvatar.Scene.TeleportClientHome(DeadAvatar.UUID, DeadAvatar.ControllingClient);
152 }
153 }
154}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeModule.cs
deleted file mode 100644
index 5ac5dbe..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeModule.cs
+++ /dev/null
@@ -1,604 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.IO;
32using System.Net;
33using System.Net.Sockets;
34using System.Reflection;
35using System.Text;
36using System.Text.RegularExpressions;
37using System.Threading;
38using log4net;
39using Nini.Config;
40using Nwc.XmlRpc;
41using OpenMetaverse;
42using OpenSim.Framework;
43using OpenSim.Framework.Servers;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Region.Environment.Modules.Avatar.Chat;
47
48namespace OpenSim.Region.Environment.Modules.Avatar.Concierge
49{
50 public class ConciergeModule : ChatModule, IRegionModule
51 {
52 private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private const int DEBUG_CHANNEL = 2147483647;
55
56 private List<IScene> _scenes = new List<IScene>();
57 private List<IScene> _conciergedScenes = new List<IScene>();
58 private Dictionary<IScene, List<UUID>> _sceneAttendees =
59 new Dictionary<IScene, List<UUID>>();
60 private Dictionary<UUID, string> _attendeeNames =
61 new Dictionary<UUID, string>();
62
63 private bool _replacingChatModule = false;
64
65 private IConfig _config;
66
67 private string _whoami = "conferencier";
68 private Regex _regions = null;
69 private string _welcomes = null;
70 private int _conciergeChannel = 42;
71 private string _announceEntering = "{0} enters {1} (now {2} visitors in this region)";
72 private string _announceLeaving = "{0} leaves {1} (back to {2} visitors in this region)";
73 private string _xmlRpcPassword = String.Empty;
74 private string _brokerURI = String.Empty;
75
76 internal object _syncy = new object();
77
78 #region IRegionModule Members
79 public override void Initialise(Scene scene, IConfigSource config)
80 {
81 try
82 {
83 if ((_config = config.Configs["Concierge"]) == null)
84 {
85 //_log.InfoFormat("[Concierge]: no configuration section [Concierge] in OpenSim.ini: module not configured");
86 return;
87 }
88
89 if (!_config.GetBoolean("enabled", false))
90 {
91 //_log.InfoFormat("[Concierge]: module disabled by OpenSim.ini configuration");
92 return;
93 }
94 }
95 catch (Exception)
96 {
97 _log.Info("[Concierge]: module not configured");
98 return;
99 }
100
101 // check whether ChatModule has been disabled: if yes,
102 // then we'll "stand in"
103 try
104 {
105 if (config.Configs["Chat"] == null)
106 {
107 _replacingChatModule = false;
108 }
109 else
110 {
111 _replacingChatModule = !config.Configs["Chat"].GetBoolean("enabled", true);
112 }
113 }
114 catch (Exception)
115 {
116 _replacingChatModule = false;
117 }
118 _log.InfoFormat("[Concierge] {0} ChatModule", _replacingChatModule ? "replacing" : "not replacing");
119
120
121 // take note of concierge channel and of identity
122 _conciergeChannel = config.Configs["Concierge"].GetInt("concierge_channel", _conciergeChannel);
123 _whoami = _config.GetString("whoami", "conferencier");
124 _welcomes = _config.GetString("welcomes", _welcomes);
125 _announceEntering = _config.GetString("announce_entering", _announceEntering);
126 _announceLeaving = _config.GetString("announce_leaving", _announceLeaving);
127 _xmlRpcPassword = _config.GetString("password", _xmlRpcPassword);
128 _brokerURI = _config.GetString("broker", _brokerURI);
129
130 _log.InfoFormat("[Concierge] reporting as \"{0}\" to our users", _whoami);
131
132 // calculate regions Regex
133 if (_regions == null)
134 {
135 string regions = _config.GetString("regions", String.Empty);
136 if (!String.IsNullOrEmpty(regions))
137 {
138 _regions = new Regex(@regions, RegexOptions.Compiled | RegexOptions.IgnoreCase);
139 }
140 }
141
142 scene.CommsManager.HttpServer.AddXmlRPCHandler("concierge_update_welcome", XmlRpcUpdateWelcomeMethod, false);
143
144 lock (_syncy)
145 {
146 if (!_scenes.Contains(scene))
147 {
148 _scenes.Add(scene);
149
150 if (_regions == null || _regions.IsMatch(scene.RegionInfo.RegionName))
151 _conciergedScenes.Add(scene);
152
153 // subscribe to NewClient events
154 scene.EventManager.OnNewClient += OnNewClient;
155
156 // subscribe to *Chat events
157 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
158 if (!_replacingChatModule)
159 scene.EventManager.OnChatFromClient += OnChatFromClient;
160 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
161
162 // subscribe to agent change events
163 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
164 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
165 }
166 }
167 _log.InfoFormat("[Concierge]: initialized for {0}", scene.RegionInfo.RegionName);
168 }
169
170 public override void PostInitialise()
171 {
172 }
173
174 public override void Close()
175 {
176 }
177
178 public override string Name
179 {
180 get { return "ConciergeModule"; }
181 }
182
183 public override bool IsSharedModule
184 {
185 get { return true; }
186 }
187
188 #endregion
189
190 #region ISimChat Members
191 public override void OnChatBroadcast(Object sender, OSChatMessage c)
192 {
193 if (_replacingChatModule)
194 {
195 // distribute chat message to each and every avatar in
196 // the region
197 base.OnChatBroadcast(sender, c);
198 }
199
200 // TODO: capture logic
201 return;
202 }
203
204 public override void OnChatFromClient(Object sender, OSChatMessage c)
205 {
206 if (_replacingChatModule)
207 {
208 // replacing ChatModule: need to redistribute
209 // ChatFromClient to interested subscribers
210 c = FixPositionOfChatMessage(c);
211
212 Scene scene = (Scene)c.Scene;
213 scene.EventManager.TriggerOnChatFromClient(sender, c);
214
215 if (_conciergedScenes.Contains(c.Scene))
216 {
217 // when we are replacing ChatModule, we treat
218 // OnChatFromClient like OnChatBroadcast for
219 // concierged regions, effectively extending the
220 // range of chat to cover the whole
221 // region. however, we don't do this for whisper
222 // (got to have some privacy)
223 if (c.Type != ChatTypeEnum.Whisper)
224 {
225 base.OnChatBroadcast(sender, c);
226 return;
227 }
228 }
229
230 // redistribution will be done by base class
231 base.OnChatFromClient(sender, c);
232 }
233
234 // TODO: capture chat
235 return;
236 }
237
238 public override void OnChatFromWorld(Object sender, OSChatMessage c)
239 {
240 if (_replacingChatModule)
241 {
242 if (_conciergedScenes.Contains(c.Scene))
243 {
244 // when we are replacing ChatModule, we treat
245 // OnChatFromClient like OnChatBroadcast for
246 // concierged regions, effectively extending the
247 // range of chat to cover the whole
248 // region. however, we don't do this for whisper
249 // (got to have some privacy)
250 if (c.Type != ChatTypeEnum.Whisper)
251 {
252 base.OnChatBroadcast(sender, c);
253 return;
254 }
255 }
256
257 base.OnChatFromWorld(sender, c);
258 }
259 return;
260 }
261 #endregion
262
263
264 public override void OnNewClient(IClientAPI client)
265 {
266 client.OnLogout += OnClientLoggedOut;
267
268 if (_replacingChatModule)
269 client.OnChatFromClient += OnChatFromClient;
270 }
271
272
273
274 public void OnClientLoggedOut(IClientAPI client)
275 {
276 client.OnLogout -= OnClientLoggedOut;
277 client.OnConnectionClosed -= OnClientLoggedOut;
278
279 if (_conciergedScenes.Contains(client.Scene))
280 {
281 _log.DebugFormat("[Concierge]: {0} logs off from {1}", client.Name, client.Scene.RegionInfo.RegionName);
282 RemoveFromAttendeeList(client.AgentId, client.Name, client.Scene);
283 AnnounceToAgentsRegion(client.Scene, String.Format(_announceLeaving, client.Name, client.Scene.RegionInfo.RegionName,
284 _sceneAttendees[client.Scene].Count));
285 UpdateBroker(client.Scene);
286 }
287 }
288
289
290 public void OnMakeRootAgent(ScenePresence agent)
291 {
292 if (_conciergedScenes.Contains(agent.Scene))
293 {
294 _log.DebugFormat("[Concierge]: {0} enters {1}", agent.Name, agent.Scene.RegionInfo.RegionName);
295 AddToAttendeeList(agent.UUID, agent.Name, agent.Scene);
296 WelcomeAvatar(agent, agent.Scene);
297 AnnounceToAgentsRegion(agent.Scene, String.Format(_announceEntering, agent.Name, agent.Scene.RegionInfo.RegionName,
298 _sceneAttendees[agent.Scene].Count));
299 UpdateBroker(agent.Scene);
300 }
301 }
302
303
304 public void OnMakeChildAgent(ScenePresence agent)
305 {
306 if (_conciergedScenes.Contains(agent.Scene))
307 {
308 _log.DebugFormat("[Concierge]: {0} leaves {1}", agent.Name, agent.Scene.RegionInfo.RegionName);
309 RemoveFromAttendeeList(agent.UUID, agent.Name, agent.Scene);
310 AnnounceToAgentsRegion(agent.Scene, String.Format(_announceLeaving, agent.Name, agent.Scene.RegionInfo.RegionName,
311 _sceneAttendees[agent.Scene].Count));
312 UpdateBroker(agent.Scene);
313 }
314 }
315
316 protected void AddToAttendeeList(UUID agentID, string name, Scene scene)
317 {
318 lock (_sceneAttendees)
319 {
320 if (!_sceneAttendees.ContainsKey(scene))
321 _sceneAttendees[scene] = new List<UUID>();
322
323 List<UUID> attendees = _sceneAttendees[scene];
324 if (!attendees.Contains(agentID))
325 {
326 attendees.Add(agentID);
327 _attendeeNames[agentID] = name;
328 }
329 }
330 }
331
332 protected void RemoveFromAttendeeList(UUID agentID, String name, IScene scene)
333 {
334 lock (_sceneAttendees)
335 {
336 if (!_sceneAttendees.ContainsKey(scene))
337 {
338 _log.WarnFormat("[Concierge]: attendee list missing for region {0}", scene.RegionInfo.RegionName);
339 return;
340 }
341
342 List<UUID> attendees = _sceneAttendees[scene];
343 if (!attendees.Contains(agentID))
344 {
345 _log.WarnFormat("[Concierge]: avatar {0} must have sneaked in to region {1} earlier",
346 name, scene.RegionInfo.RegionName);
347 return;
348 }
349
350 attendees.Remove(agentID);
351 _attendeeNames.Remove(agentID);
352 }
353 }
354
355 protected void UpdateBroker(IScene scene)
356 {
357 if (String.IsNullOrEmpty(_brokerURI))
358 return;
359
360 string uri = String.Format(_brokerURI, scene.RegionInfo.RegionName, scene.RegionInfo.RegionID);
361
362 // get attendee list for the scene
363 List<UUID> attendees;
364 lock (_sceneAttendees)
365 {
366 if (!_sceneAttendees.ContainsKey(scene))
367 {
368 _log.DebugFormat("[Concierge]: attendee list missing for region {0}", scene.RegionInfo.RegionName);
369 return;
370 }
371
372 attendees = _sceneAttendees[scene];
373 }
374
375 // create XML sniplet
376 StringBuilder list = new StringBuilder();
377 if (0 == attendees.Count)
378 {
379 list.Append(String.Format("<avatars count=\"0\" region_name=\"{0}\" region_uuid=\"{1}\" timestamp=\"{2}\" />",
380 scene.RegionInfo.RegionName, scene.RegionInfo.RegionID,
381 DateTime.UtcNow.ToString("s")));
382 }
383 else
384 {
385 list.Append(String.Format("<avatars count=\"{0}\" region_name=\"{1}\" region_uuid=\"{2}\" timestamp=\"{3}\">\n",
386 attendees.Count, scene.RegionInfo.RegionName,
387 scene.RegionInfo.RegionID,
388 DateTime.UtcNow.ToString("s")));
389 foreach (UUID uuid in attendees)
390 {
391 string name = _attendeeNames[uuid];
392 list.Append(String.Format(" <avatar name=\"{0}\" uuid=\"{1}\" />\n", name, uuid));
393 }
394 list.Append("</avatars>");
395 }
396 string payload = list.ToString();
397
398 // post via REST to broker
399 HttpWebRequest updatePost = WebRequest.Create(uri) as HttpWebRequest;
400 updatePost.Method = "POST";
401 updatePost.ContentType = "text/xml";
402 updatePost.ContentLength = payload.Length;
403 updatePost.UserAgent = "OpenSim.Concierge";
404
405 try
406 {
407 StreamWriter payloadStream = new StreamWriter(updatePost.GetRequestStream());
408 payloadStream.Write(payload);
409 payloadStream.Close();
410
411 updatePost.BeginGetResponse(UpdateBrokerDone, updatePost);
412 _log.DebugFormat("[Concierge] async broker POST to {0} started", uri);
413 }
414 catch (WebException we)
415 {
416 _log.ErrorFormat("[Concierge] async broker POST to {0} failed: {1}", uri, we.Status);
417 }
418 }
419
420 private void UpdateBrokerDone(IAsyncResult result)
421 {
422 HttpWebRequest updatePost = null;
423 try
424 {
425 updatePost = result.AsyncState as HttpWebRequest;
426 using (HttpWebResponse response = updatePost.EndGetResponse(result) as HttpWebResponse)
427 {
428 _log.DebugFormat("[Concierge] broker update: status {0}", response.StatusCode);
429 }
430 }
431 catch (WebException we)
432 {
433 string uri = updatePost.RequestUri.OriginalString;
434 _log.ErrorFormat("[Concierge] broker update to {0} failed with status {1}", uri, we.Status);
435 if (null != we.Response)
436 {
437 using (HttpWebResponse resp = we.Response as HttpWebResponse)
438 {
439 _log.ErrorFormat("[Concierge] response from {0} status code: {1}", uri, resp.StatusCode);
440 _log.ErrorFormat("[Concierge] response from {0} status desc: {1}", uri, resp.StatusDescription);
441 _log.ErrorFormat("[Concierge] response from {0} server: {1}", uri, resp.Server);
442
443 if (resp.ContentLength > 0)
444 {
445 StreamReader content = new StreamReader(resp.GetResponseStream());
446 _log.ErrorFormat("[Concierge] response from {0} content: {1}", uri, content.ReadToEnd());
447 content.Close();
448 }
449 }
450 }
451 }
452 }
453
454 protected void WelcomeAvatar(ScenePresence agent, Scene scene)
455 {
456 // welcome mechanics: check whether we have a welcomes
457 // directory set and wether there is a region specific
458 // welcome file there: if yes, send it to the agent
459 if (!String.IsNullOrEmpty(_welcomes))
460 {
461 string[] welcomes = new string[] {
462 Path.Combine(_welcomes, agent.Scene.RegionInfo.RegionName),
463 Path.Combine(_welcomes, "DEFAULT")};
464 foreach (string welcome in welcomes)
465 {
466 if (File.Exists(welcome))
467 {
468 try
469 {
470 string[] welcomeLines = File.ReadAllLines(welcome);
471 foreach (string l in welcomeLines)
472 {
473 AnnounceToAgent(agent, String.Format(l, agent.Name, scene.RegionInfo.RegionName, _whoami));
474 }
475 }
476 catch (IOException ioe)
477 {
478 _log.ErrorFormat("[Concierge]: run into trouble reading welcome file {0} for region {1} for avatar {2}: {3}",
479 welcome, scene.RegionInfo.RegionName, agent.Name, ioe);
480 }
481 catch (FormatException fe)
482 {
483 _log.ErrorFormat("[Concierge]: welcome file {0} is malformed: {1}", welcome, fe);
484 }
485 }
486 return;
487 }
488 _log.DebugFormat("[Concierge]: no welcome message for region {0}", scene.RegionInfo.RegionName);
489 }
490 }
491
492 static private Vector3 PosOfGod = new Vector3(128, 128, 9999);
493
494 // protected void AnnounceToAgentsRegion(Scene scene, string msg)
495 // {
496 // ScenePresence agent = null;
497 // if ((client.Scene is Scene) && (client.Scene as Scene).TryGetAvatar(client.AgentId, out agent))
498 // AnnounceToAgentsRegion(agent, msg);
499 // else
500 // _log.DebugFormat("[Concierge]: could not find an agent for client {0}", client.Name);
501 // }
502
503 protected void AnnounceToAgentsRegion(IScene scene, string msg)
504 {
505 OSChatMessage c = new OSChatMessage();
506 c.Message = msg;
507 c.Type = ChatTypeEnum.Say;
508 c.Channel = 0;
509 c.Position = PosOfGod;
510 c.From = _whoami;
511 c.Sender = null;
512 c.SenderUUID = UUID.Zero;
513 c.Scene = scene;
514
515 if (scene is Scene)
516 (scene as Scene).EventManager.TriggerOnChatBroadcast(this, c);
517 }
518
519 protected void AnnounceToAgent(ScenePresence agent, string msg)
520 {
521 OSChatMessage c = new OSChatMessage();
522 c.Message = msg;
523 c.Type = ChatTypeEnum.Say;
524 c.Channel = 0;
525 c.Position = PosOfGod;
526 c.From = _whoami;
527 c.Sender = null;
528 c.SenderUUID = UUID.Zero;
529 c.Scene = agent.Scene;
530
531 agent.ControllingClient.SendChatMessage(msg, (byte) ChatTypeEnum.Say, PosOfGod, _whoami, UUID.Zero,
532 (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully);
533 }
534
535 private static void checkStringParameters(XmlRpcRequest request, string[] param)
536 {
537 Hashtable requestData = (Hashtable) request.Params[0];
538 foreach (string p in param)
539 {
540 if (!requestData.Contains(p))
541 throw new Exception(String.Format("missing string parameter {0}", p));
542 if (String.IsNullOrEmpty((string)requestData[p]))
543 throw new Exception(String.Format("parameter {0} is empty", p));
544 }
545 }
546
547 public XmlRpcResponse XmlRpcUpdateWelcomeMethod(XmlRpcRequest request)
548 {
549 _log.Info("[Concierge]: processing UpdateWelcome request");
550 XmlRpcResponse response = new XmlRpcResponse();
551 Hashtable responseData = new Hashtable();
552
553 try
554 {
555 Hashtable requestData = (Hashtable)request.Params[0];
556 checkStringParameters(request, new string[] { "password", "region", "welcome" });
557
558 // check password
559 if (!String.IsNullOrEmpty(_xmlRpcPassword) &&
560 (string)requestData["password"] != _xmlRpcPassword) throw new Exception("wrong password");
561
562 if (String.IsNullOrEmpty(_welcomes))
563 throw new Exception("welcome templates are not enabled, ask your OpenSim operator to set the \"welcomes\" option in the [Concierge] section of OpenSim.ini");
564
565 string msg = (string)requestData["welcome"];
566 if (String.IsNullOrEmpty(msg))
567 throw new Exception("empty parameter \"welcome\"");
568
569 string regionName = (string)requestData["region"];
570 IScene scene = _scenes.Find(delegate(IScene s) { return s.RegionInfo.RegionName == regionName; });
571 if (scene == null)
572 throw new Exception(String.Format("unknown region \"{0}\"", regionName));
573
574 if (!_conciergedScenes.Contains(scene))
575 throw new Exception(String.Format("region \"{0}\" is not a concierged region.", regionName));
576
577 string welcome = Path.Combine(_welcomes, regionName);
578 if (File.Exists(welcome))
579 {
580 _log.InfoFormat("[Concierge]: UpdateWelcome: updating existing template \"{0}\"", welcome);
581 string welcomeBackup = String.Format("{0}~", welcome);
582 if (File.Exists(welcomeBackup))
583 File.Delete(welcomeBackup);
584 File.Move(welcome, welcomeBackup);
585 }
586 File.WriteAllText(welcome, msg);
587
588 responseData["success"] = "true";
589 response.Value = responseData;
590 }
591 catch (Exception e)
592 {
593 _log.InfoFormat("[Concierge]: UpdateWelcome failed: {0}", e.Message);
594
595 responseData["success"] = "false";
596 responseData["error"] = e.Message;
597
598 response.Value = responseData;
599 }
600 _log.Debug("[Concierge]: done processing UpdateWelcome request");
601 return response;
602 }
603 }
604}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeServer.py b/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeServer.py
deleted file mode 100755
index 1c088fb..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeServer.py
+++ /dev/null
@@ -1,130 +0,0 @@
1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3#
4# Copyright (c) Contributors, http://opensimulator.org/
5# See CONTRIBUTORS.TXT for a full list of copyright holders.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9# * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above copyright
12# notice, this list of conditions and the following disclaimer in the
13# documentation and/or other materials provided with the distribution.
14# * Neither the name of the OpenSim Project nor the
15# names of its contributors may be used to endorse or promote products
16# derived from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
19# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21# DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
22# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29
30import logging
31import BaseHTTPServer
32import optparse
33import xml.etree.ElementTree as ET
34import xml.parsers.expat
35
36
37# enable debug level logging
38logging.basicConfig(level = logging.DEBUG,
39 format='%(asctime)s %(levelname)s %(message)s')
40
41options = None
42
43# subclassed HTTPRequestHandler
44class ConciergeHandler(BaseHTTPServer.BaseHTTPRequestHandler):
45 def logRequest(self):
46 logging.info('[ConciergeHandler] %(command)s request: %(host)s:%(port)d --- %(path)s',
47 dict(command = self.command,
48 host = self.client_address[0],
49 port = self.client_address[1],
50 path = self.path))
51
52 def logResponse(self, status):
53 logging.info('[ConciergeHandler] %(command)s returned %(status)d',
54 dict(command = self.command,
55 status = status))
56
57
58 def do_HEAD(self):
59 self.logRequest()
60
61 self.send_response(200)
62 self.send_header('Content-type', 'text/html')
63 self.end_headers()
64
65 self.logResponse(200)
66
67 def dumpXml(self, xml):
68 logging.debug('[ConciergeHandler] %s', xml.tag)
69 for attr in xml.attrib:
70 logging.debug('[ConciergeHandler] %s [%s] %s', xml.tag, attr, xml.attrib[attr])
71 for kid in xml.getchildren():
72 self.dumpXml(kid)
73
74 def do_POST(self):
75 self.logRequest()
76 hdrs = {}
77 for hdr in self.headers.headers:
78 logging.debug('[ConciergeHandler] POST: header: %s', hdr.rstrip())
79
80 length = int(self.headers.getheader('Content-Length'))
81 content = self.rfile.read(length)
82 self.rfile.close()
83
84 logging.debug('[ConciergeHandler] POST: content: %s', content)
85 try:
86 postXml = ET.fromstring(content)
87 self.dumpXml(postXml)
88 except xml.parsers.expat.ExpatError, xmlError:
89 logging.error('[ConciergeHandler] POST illformed:%s', xmlError)
90 self.send_response(500)
91 return
92
93 if not options.fail:
94 self.send_response(200)
95 self.send_header('Content-Type', 'text/html')
96 self.send_header('Content-Length', len('<success/>'))
97 self.end_headers()
98 self.logResponse(200)
99 self.wfile.write('<success/>')
100 self.wfile.close()
101 else:
102 self.send_response(500)
103 self.send_header('Content-Type', 'text/html')
104 self.send_header('Content-Length', len('<error>gotcha!</error>'))
105 self.end_headers()
106 self.wfile.write('<error>gotcha!</error>')
107 self.wfile.close()
108
109 self.logResponse(500)
110
111 def log_request(code, size):
112 pass
113
114if __name__ == '__main__':
115
116 logging.info('[ConciergeServer] Concierge Broker Test Server starting')
117
118 parser = optparse.OptionParser()
119 parser.add_option('-p', '--port', dest = 'port', help = 'port to listen on', metavar = 'PORT')
120 parser.add_option('-f', '--fail', dest = 'fail', action = 'store_true', help = 'always fail POST requests')
121
122 (options, args) = parser.parse_args()
123
124 httpServer = BaseHTTPServer.HTTPServer(('', 8080), ConciergeHandler)
125 try:
126 httpServer.serve_forever()
127 except KeyboardInterrupt:
128 logging.info('[ConciergeServer] terminating')
129
130 httpServer.server_close()
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs
deleted file mode 100644
index 1ec5e9b..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs
+++ /dev/null
@@ -1,1605 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Net.Sockets;
33using System.Reflection;
34using System.Xml;
35using log4net;
36using Nini.Config;
37using Nwc.XmlRpc;
38using OpenMetaverse;
39using OpenSim.Framework;
40using OpenSim.Framework.Communications.Cache;
41using OpenSim.Framework.Servers;
42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes;
44
45namespace OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney
46{
47 /// <summary>
48 /// Demo Economy/Money Module. This is not a production quality money/economy module!
49 /// This is a demo for you to use when making one that works for you.
50 /// // To use the following you need to add:
51 /// -helperuri <ADDRESS TO HERE OR grid MONEY SERVER>
52 /// to the command line parameters you use to start up your client
53 /// This commonly looks like -helperuri http://127.0.0.1:9000/
54 ///
55 /// Centralized grid structure example using OpenSimWi Redux revision 9+
56 /// svn co https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux
57 /// </summary>
58 public class SampleMoneyModule : IMoneyModule, IRegionModule
59 {
60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61
62 /// <summary>
63 /// Where Stipends come from and Fees go to.
64 /// </summary>
65 // private UUID EconomyBaseAccount = UUID.Zero;
66
67 private float EnergyEfficiency = 0f;
68 private bool gridmode = false;
69 // private ObjectPaid handerOnObjectPaid;
70 private bool m_enabled = true;
71
72 private IConfigSource m_gConfig;
73
74 private bool m_keepMoneyAcrossLogins = true;
75 private Dictionary<UUID, int> m_KnownClientFunds = new Dictionary<UUID, int>();
76 // private string m_LandAddress = String.Empty;
77
78 private int m_minFundsBeforeRefresh = 100;
79 private string m_MoneyAddress = String.Empty;
80
81 /// <summary>
82 /// Region UUIDS indexed by AgentID
83 /// </summary>
84 private Dictionary<UUID, UUID> m_rootAgents = new Dictionary<UUID, UUID>();
85
86 /// <summary>
87 /// Scenes by Region Handle
88 /// </summary>
89 private Dictionary<ulong, Scene> m_scenel = new Dictionary<ulong, Scene>();
90
91 private int m_stipend = 1000;
92
93 private int ObjectCapacity = 45000;
94 private int ObjectCount = 0;
95 private int PriceEnergyUnit = 0;
96 private int PriceGroupCreate = 0;
97 private int PriceObjectClaim = 0;
98 private float PriceObjectRent = 0f;
99 private float PriceObjectScaleFactor = 0f;
100 private int PriceParcelClaim = 0;
101 private float PriceParcelClaimFactor = 0f;
102 private int PriceParcelRent = 0;
103 private int PricePublicObjectDecay = 0;
104 private int PricePublicObjectDelete = 0;
105 private int PriceRentLight = 0;
106 private int PriceUpload = 0;
107 private int TeleportMinPrice = 0;
108
109 private float TeleportPriceExponent = 0f;
110 // private int UserLevelPaysFees = 2;
111 // private Scene XMLRPCHandler;
112
113 #region IMoneyModule Members
114
115 public event ObjectPaid OnObjectPaid;
116
117 /// <summary>
118 /// Startup
119 /// </summary>
120 /// <param name="scene"></param>
121 /// <param name="config"></param>
122 public void Initialise(Scene scene, IConfigSource config)
123 {
124 m_gConfig = config;
125
126 IConfig startupConfig = m_gConfig.Configs["Startup"];
127 IConfig economyConfig = m_gConfig.Configs["Economy"];
128
129
130 ReadConfigAndPopulate(scene, startupConfig, "Startup");
131 ReadConfigAndPopulate(scene, economyConfig, "Economy");
132
133 if (m_enabled)
134 {
135 scene.RegisterModuleInterface<IMoneyModule>(this);
136 BaseHttpServer httpServer = scene.CommsManager.HttpServer;
137
138 lock (m_scenel)
139 {
140 if (m_scenel.Count == 0)
141 {
142 // XMLRPCHandler = scene;
143
144 // To use the following you need to add:
145 // -helperuri <ADDRESS TO HERE OR grid MONEY SERVER>
146 // to the command line parameters you use to start up your client
147 // This commonly looks like -helperuri http://127.0.0.1:9000/
148
149 if (m_MoneyAddress.Length > 0)
150 {
151 // Centralized grid structure using OpenSimWi Redux revision 9+
152 // https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux
153 httpServer.AddXmlRPCHandler("balanceUpdateRequest", GridMoneyUpdate);
154 httpServer.AddXmlRPCHandler("userAlert", UserAlert);
155 }
156 else
157 {
158 // Local Server.. enables functionality only.
159 httpServer.AddXmlRPCHandler("getCurrencyQuote", quote_func);
160 httpServer.AddXmlRPCHandler("buyCurrency", buy_func);
161 httpServer.AddXmlRPCHandler("preflightBuyLandPrep", preflightBuyLandPrep_func);
162 httpServer.AddXmlRPCHandler("buyLandPrep", landBuy_func);
163 }
164 }
165
166 if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle))
167 {
168 m_scenel[scene.RegionInfo.RegionHandle] = scene;
169 }
170 else
171 {
172 m_scenel.Add(scene.RegionInfo.RegionHandle, scene);
173 }
174 }
175
176 scene.EventManager.OnNewClient += OnNewClient;
177 scene.EventManager.OnMoneyTransfer += MoneyTransferAction;
178 scene.EventManager.OnClientClosed += ClientClosed;
179 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
180 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
181 scene.EventManager.OnClientClosed += ClientLoggedOut;
182 scene.EventManager.OnValidateLandBuy += ValidateLandBuy;
183 scene.EventManager.OnLandBuy += processLandBuy;
184 }
185 }
186
187 // Please do not refactor these to be just one method
188 // Existing implementations need the distinction
189 //
190 public void ApplyUploadCharge(UUID agentID)
191 {
192 }
193
194 public void ApplyGroupCreationCharge(UUID agentID)
195 {
196 }
197
198 public void ApplyCharge(UUID agentID, int amount, string text)
199 {
200 }
201
202 public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount)
203 {
204 string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID));
205
206 bool give_result = doMoneyTransfer(fromID, toID, amount, 2, description);
207
208 if (m_MoneyAddress.Length == 0)
209 BalanceUpdate(fromID, toID, give_result, description);
210
211 return give_result;
212 }
213
214 public void PostInitialise()
215 {
216 }
217
218 public void Close()
219 {
220 }
221
222 public string Name
223 {
224 get { return "BetaGridLikeMoneyModule"; }
225 }
226
227 public bool IsSharedModule
228 {
229 get { return true; }
230 }
231
232 #endregion
233
234 /// <summary>
235 /// Parse Configuration
236 /// </summary>
237 /// <param name="scene"></param>
238 /// <param name="startupConfig"></param>
239 /// <param name="config"></param>
240 private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string config)
241 {
242 if (config == "Startup" && startupConfig != null)
243 {
244 gridmode = startupConfig.GetBoolean("gridmode", false);
245 m_enabled = (startupConfig.GetString("economymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule");
246 }
247
248 if (config == "Economy" && startupConfig != null)
249 {
250 ObjectCapacity = startupConfig.GetInt("ObjectCapacity", 45000);
251 PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100);
252 PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10);
253 PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4);
254 PricePublicObjectDelete = startupConfig.GetInt("PricePublicObjectDelete", 4);
255 PriceParcelClaim = startupConfig.GetInt("PriceParcelClaim", 1);
256 PriceParcelClaimFactor = startupConfig.GetFloat("PriceParcelClaimFactor", 1f);
257 PriceUpload = startupConfig.GetInt("PriceUpload", 0);
258 PriceRentLight = startupConfig.GetInt("PriceRentLight", 5);
259 TeleportMinPrice = startupConfig.GetInt("TeleportMinPrice", 2);
260 TeleportPriceExponent = startupConfig.GetFloat("TeleportPriceExponent", 2f);
261 EnergyEfficiency = startupConfig.GetFloat("EnergyEfficiency", 1);
262 PriceObjectRent = startupConfig.GetFloat("PriceObjectRent", 1);
263 PriceObjectScaleFactor = startupConfig.GetFloat("PriceObjectScaleFactor", 10);
264 PriceParcelRent = startupConfig.GetInt("PriceParcelRent", 1);
265 PriceGroupCreate = startupConfig.GetInt("PriceGroupCreate", -1);
266 // string EBA = startupConfig.GetString("EconomyBaseAccount", UUID.Zero.ToString());
267 // Helpers.TryParse(EBA, out EconomyBaseAccount);
268
269 // UserLevelPaysFees = startupConfig.GetInt("UserLevelPaysFees", -1);
270 m_stipend = startupConfig.GetInt("UserStipend", 500);
271 m_minFundsBeforeRefresh = startupConfig.GetInt("IssueStipendWhenClientIsBelowAmount", 10);
272 m_keepMoneyAcrossLogins = startupConfig.GetBoolean("KeepMoneyAcrossLogins", true);
273 m_MoneyAddress = startupConfig.GetString("CurrencyServer", String.Empty);
274 // m_LandAddress = startupConfig.GetString("LandServer", String.Empty);
275 }
276
277 // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter.
278 scene.SetObjectCapacity(ObjectCapacity);
279 }
280
281 public EconomyData GetEconomyData()
282 {
283 EconomyData edata = new EconomyData();
284 edata.ObjectCapacity = ObjectCapacity;
285 edata.ObjectCount = ObjectCount;
286 edata.PriceEnergyUnit = PriceEnergyUnit;
287 edata.PriceGroupCreate = PriceGroupCreate;
288 edata.PriceObjectClaim = PriceObjectClaim;
289 edata.PriceObjectRent = PriceObjectRent;
290 edata.PriceObjectScaleFactor = PriceObjectScaleFactor;
291 edata.PriceParcelClaim = PriceParcelClaim;
292 edata.PriceParcelClaimFactor = PriceParcelClaimFactor;
293 edata.PriceParcelRent = PriceParcelRent;
294 edata.PricePublicObjectDecay = PricePublicObjectDecay;
295 edata.PricePublicObjectDelete = PricePublicObjectDelete;
296 edata.PriceRentLight = PriceRentLight;
297 edata.PriceUpload = PriceUpload;
298 edata.TeleportMinPrice = TeleportMinPrice;
299 return edata;
300 }
301
302 private void GetClientFunds(IClientAPI client)
303 {
304 // Here we check if we're in grid mode
305 // I imagine that the 'check balance'
306 // function for the client should be here or shortly after
307
308 if (gridmode)
309 {
310 if (m_MoneyAddress.Length == 0)
311 {
312 CheckExistAndRefreshFunds(client.AgentId);
313 }
314 else
315 {
316 bool childYN = true;
317 ScenePresence agent = null;
318 //client.SecureSessionId;
319 Scene s = LocateSceneClientIn(client.AgentId);
320 if (s != null)
321 {
322 agent = s.GetScenePresence(client.AgentId);
323 if (agent != null)
324 childYN = agent.IsChildAgent;
325 }
326 if (s != null && agent != null && childYN == false)
327 {
328 //s.RegionInfo.RegionHandle;
329 UUID agentID = UUID.Zero;
330 int funds = 0;
331
332 Hashtable hbinfo =
333 GetBalanceForUserFromMoneyServer(client.AgentId, client.SecureSessionId, s.RegionInfo.originRegionID,
334 s.RegionInfo.regionSecret);
335 if ((bool) hbinfo["success"] == true)
336 {
337 UUID.TryParse((string)hbinfo["agentId"], out agentID);
338 try
339 {
340 funds = (Int32) hbinfo["funds"];
341 }
342 catch (ArgumentException)
343 {
344 }
345 catch (FormatException)
346 {
347 }
348 catch (OverflowException)
349 {
350 m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentID);
351 client.SendAlertMessage("Unable to get your money balance, money operations will be unavailable");
352 }
353 catch (InvalidCastException)
354 {
355 funds = 0;
356 }
357
358 m_KnownClientFunds[agentID] = funds;
359 }
360 else
361 {
362 m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentID,
363 (string) hbinfo["errorMessage"]);
364 client.SendAlertMessage((string) hbinfo["errorMessage"]);
365 }
366 SendMoneyBalance(client, agentID, client.SessionId, UUID.Zero);
367 }
368 }
369 }
370 else
371 {
372 CheckExistAndRefreshFunds(client.AgentId);
373 }
374
375 }
376
377 /// <summary>
378 /// New Client Event Handler
379 /// </summary>
380 /// <param name="client"></param>
381 private void OnNewClient(IClientAPI client)
382 {
383 GetClientFunds(client);
384
385 // Subscribe to Money messages
386 client.OnEconomyDataRequest += EconomyDataRequestHandler;
387 client.OnMoneyBalanceRequest += SendMoneyBalance;
388 client.OnRequestPayPrice += requestPayPrice;
389 client.OnObjectBuy += ObjectBuy;
390 client.OnLogout += ClientClosed;
391 }
392
393 /// <summary>
394 /// Transfer money
395 /// </summary>
396 /// <param name="Sender"></param>
397 /// <param name="Receiver"></param>
398 /// <param name="amount"></param>
399 /// <returns></returns>
400 private bool doMoneyTransfer(UUID Sender, UUID Receiver, int amount, int transactiontype, string description)
401 {
402 bool result = false;
403 if (amount >= 0)
404 {
405 lock (m_KnownClientFunds)
406 {
407 // If we don't know about the sender, then the sender can't
408 // actually be here and therefore this is likely fraud or outdated.
409 if (m_MoneyAddress.Length == 0)
410 {
411 if (m_KnownClientFunds.ContainsKey(Sender))
412 {
413 // Does the sender have enough funds to give?
414 if (m_KnownClientFunds[Sender] >= amount)
415 {
416 // Subtract the funds from the senders account
417 m_KnownClientFunds[Sender] -= amount;
418
419 // do we know about the receiver?
420 if (!m_KnownClientFunds.ContainsKey(Receiver))
421 {
422 // Make a record for them so they get the updated balance when they login
423 CheckExistAndRefreshFunds(Receiver);
424 }
425 if (m_enabled)
426 {
427 //Add the amount to the Receiver's funds
428 m_KnownClientFunds[Receiver] += amount;
429 result = true;
430 }
431 }
432 else
433 {
434 // These below are redundant to make this clearer to read
435 result = false;
436 }
437 }
438 else
439 {
440 result = false;
441 }
442 }
443 else
444 {
445 result = TransferMoneyonMoneyServer(Sender, Receiver, amount, transactiontype, description);
446 }
447 }
448 }
449 return result;
450 }
451
452
453 /// <summary>
454 /// Sends the the stored money balance to the client
455 /// </summary>
456 /// <param name="client"></param>
457 /// <param name="agentID"></param>
458 /// <param name="SessionID"></param>
459 /// <param name="TransactionID"></param>
460 public void SendMoneyBalance(IClientAPI client, UUID agentID, UUID SessionID, UUID TransactionID)
461 {
462 if (client.AgentId == agentID && client.SessionId == SessionID)
463 {
464 int returnfunds = 0;
465
466 try
467 {
468 returnfunds = GetFundsForAgentID(agentID);
469 }
470 catch (Exception e)
471 {
472 client.SendAlertMessage(e.Message + " ");
473 }
474
475 client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds);
476 }
477 else
478 {
479 client.SendAlertMessage("Unable to send your money balance to you!");
480 }
481 }
482
483 /// <summary>
484 /// Gets the current balance for the user from the Grid Money Server
485 /// </summary>
486 /// <param name="agentId"></param>
487 /// <param name="secureSessionID"></param>
488 /// <param name="regionId"></param>
489 /// <param name="regionSecret"></param>
490 /// <returns></returns>
491 public Hashtable GetBalanceForUserFromMoneyServer(UUID agentId, UUID secureSessionID, UUID regionId, string regionSecret)
492 {
493 Hashtable MoneyBalanceRequestParams = new Hashtable();
494 MoneyBalanceRequestParams["agentId"] = agentId.ToString();
495 MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString();
496 MoneyBalanceRequestParams["regionId"] = regionId.ToString();
497 MoneyBalanceRequestParams["secret"] = regionSecret;
498 MoneyBalanceRequestParams["currencySecret"] = ""; // per - region/user currency secret gotten from the money system
499
500 Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorUserBalanceRequest");
501
502 return MoneyRespData;
503 }
504
505
506 /// <summary>
507 /// Generic XMLRPC client abstraction
508 /// </summary>
509 /// <param name="ReqParams">Hashtable containing parameters to the method</param>
510 /// <param name="method">Method to invoke</param>
511 /// <returns>Hashtable with success=>bool and other values</returns>
512 public Hashtable genericCurrencyXMLRPCRequest(Hashtable ReqParams, string method)
513 {
514 ArrayList SendParams = new ArrayList();
515 SendParams.Add(ReqParams);
516 // Send Request
517 XmlRpcResponse MoneyResp;
518 try
519 {
520 XmlRpcRequest BalanceRequestReq = new XmlRpcRequest(method, SendParams);
521 MoneyResp = BalanceRequestReq.Send(m_MoneyAddress, 30000);
522 }
523 catch (WebException ex)
524 {
525 m_log.ErrorFormat(
526 "[MONEY]: Unable to connect to Money Server {0}. Exception {1}",
527 m_MoneyAddress, ex);
528
529 Hashtable ErrorHash = new Hashtable();
530 ErrorHash["success"] = false;
531 ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
532 ErrorHash["errorURI"] = "";
533
534 return ErrorHash;
535 //throw (ex);
536 }
537 catch (SocketException ex)
538 {
539 m_log.ErrorFormat(
540 "[MONEY]: Unable to connect to Money Server {0}. Exception {1}",
541 m_MoneyAddress, ex);
542
543 Hashtable ErrorHash = new Hashtable();
544 ErrorHash["success"] = false;
545 ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
546 ErrorHash["errorURI"] = "";
547
548 return ErrorHash;
549 //throw (ex);
550 }
551 catch (XmlException ex)
552 {
553 m_log.ErrorFormat(
554 "[MONEY]: Unable to connect to Money Server {0}. Exception {1}",
555 m_MoneyAddress, ex);
556
557 Hashtable ErrorHash = new Hashtable();
558 ErrorHash["success"] = false;
559 ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
560 ErrorHash["errorURI"] = "";
561
562 return ErrorHash;
563 }
564 if (MoneyResp.IsFault)
565 {
566 Hashtable ErrorHash = new Hashtable();
567 ErrorHash["success"] = false;
568 ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable";
569 ErrorHash["errorURI"] = "";
570
571 return ErrorHash;
572 }
573 Hashtable MoneyRespData = (Hashtable) MoneyResp.Value;
574
575 return MoneyRespData;
576 }
577
578 /// <summary>
579 /// This informs the Money Grid Server that the avatar is in this simulator
580 /// </summary>
581 /// <param name="agentId"></param>
582 /// <param name="secureSessionID"></param>
583 /// <param name="regionId"></param>
584 /// <param name="regionSecret"></param>
585 /// <returns></returns>
586 public Hashtable claim_user(UUID agentId, UUID secureSessionID, UUID regionId, string regionSecret)
587 {
588 Hashtable MoneyBalanceRequestParams = new Hashtable();
589 MoneyBalanceRequestParams["agentId"] = agentId.ToString();
590 MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString();
591 MoneyBalanceRequestParams["regionId"] = regionId.ToString();
592 MoneyBalanceRequestParams["secret"] = regionSecret;
593
594 Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorClaimUserRequest");
595 IClientAPI sendMoneyBal = LocateClientObject(agentId);
596 if (sendMoneyBal != null)
597 {
598 SendMoneyBalance(sendMoneyBal, agentId, sendMoneyBal.SessionId, UUID.Zero);
599 }
600 return MoneyRespData;
601 }
602
603 private SceneObjectPart findPrim(UUID objectID)
604 {
605 lock (m_scenel)
606 {
607 foreach (Scene s in m_scenel.Values)
608 {
609 SceneObjectPart part = s.GetSceneObjectPart(objectID);
610 if (part != null)
611 {
612 return part;
613 }
614 }
615 }
616 return null;
617 }
618
619 private string resolveObjectName(UUID objectID)
620 {
621 SceneObjectPart part = findPrim(objectID);
622 if (part != null)
623 {
624 return part.Name;
625 }
626 return String.Empty;
627 }
628
629 private string resolveAgentName(UUID agentID)
630 {
631 // try avatar username surname
632 Scene scene = GetRandomScene();
633 CachedUserInfo profile = scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
634 if (profile != null && profile.UserProfile != null)
635 {
636 string avatarname = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName;
637 return avatarname;
638 }
639 else
640 {
641 m_log.ErrorFormat(
642 "[MONEY]: Could not resolve user {0}",
643 agentID);
644 }
645
646 return String.Empty;
647 }
648
649 private void BalanceUpdate(UUID senderID, UUID receiverID, bool transactionresult, string description)
650 {
651 IClientAPI sender = LocateClientObject(senderID);
652 IClientAPI receiver = LocateClientObject(receiverID);
653
654 if (senderID != receiverID)
655 {
656 if (sender != null)
657 {
658 sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(senderID));
659 }
660
661 if (receiver != null)
662 {
663 receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(receiverID));
664 }
665 }
666 }
667
668 /// <summary>
669 /// Informs the Money Grid Server of a transfer.
670 /// </summary>
671 /// <param name="sourceId"></param>
672 /// <param name="destId"></param>
673 /// <param name="amount"></param>
674 /// <returns></returns>
675 public bool TransferMoneyonMoneyServer(UUID sourceId, UUID destId, int amount, int transactiontype, string description)
676 {
677 int aggregatePermInventory = 0;
678 int aggregatePermNextOwner = 0;
679 int flags = 0;
680 bool rvalue = false;
681
682 IClientAPI cli = LocateClientObject(sourceId);
683 if (cli != null)
684 {
685 Scene userScene = null;
686 lock (m_rootAgents)
687 {
688 userScene = GetSceneByUUID(m_rootAgents[sourceId]);
689 }
690 if (userScene != null)
691 {
692 Hashtable ht = new Hashtable();
693 ht["agentId"] = sourceId.ToString();
694 ht["secureSessionId"] = cli.SecureSessionId.ToString();
695 ht["regionId"] = userScene.RegionInfo.originRegionID.ToString();
696 ht["secret"] = userScene.RegionInfo.regionSecret;
697 ht["currencySecret"] = " ";
698 ht["destId"] = destId.ToString();
699 ht["cash"] = amount;
700 ht["aggregatePermInventory"] = aggregatePermInventory;
701 ht["aggregatePermNextOwner"] = aggregatePermNextOwner;
702 ht["flags"] = flags;
703 ht["transactionType"] = transactiontype;
704 ht["description"] = description;
705
706 Hashtable hresult = genericCurrencyXMLRPCRequest(ht, "regionMoveMoney");
707
708 if ((bool) hresult["success"] == true)
709 {
710 int funds1 = 0;
711 int funds2 = 0;
712 try
713 {
714 funds1 = (Int32) hresult["funds"];
715 }
716 catch (InvalidCastException)
717 {
718 funds1 = 0;
719 }
720 SetLocalFundsForAgentID(sourceId, funds1);
721 if (m_KnownClientFunds.ContainsKey(destId))
722 {
723 try
724 {
725 funds2 = (Int32) hresult["funds2"];
726 }
727 catch (InvalidCastException)
728 {
729 funds2 = 0;
730 }
731 SetLocalFundsForAgentID(destId, funds2);
732 }
733
734
735 rvalue = true;
736 }
737 else
738 {
739 cli.SendAgentAlertMessage((string) hresult["errorMessage"], true);
740 }
741 }
742 }
743 else
744 {
745 m_log.ErrorFormat("[MONEY]: Client {0} not found", sourceId.ToString());
746 }
747
748 return rvalue;
749 }
750
751 public int GetRemoteBalance(UUID agentId)
752 {
753 int funds = 0;
754
755 IClientAPI aClient = LocateClientObject(agentId);
756 if (aClient != null)
757 {
758 Scene s = LocateSceneClientIn(agentId);
759 if (s != null)
760 {
761 if (m_MoneyAddress.Length > 0)
762 {
763 Hashtable hbinfo =
764 GetBalanceForUserFromMoneyServer(aClient.AgentId, aClient.SecureSessionId, s.RegionInfo.originRegionID,
765 s.RegionInfo.regionSecret);
766 if ((bool) hbinfo["success"] == true)
767 {
768 try
769 {
770 funds = (Int32) hbinfo["funds"];
771 }
772 catch (ArgumentException)
773 {
774 }
775 catch (FormatException)
776 {
777 }
778 catch (OverflowException)
779 {
780 m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentId);
781 aClient.SendAlertMessage("Unable to get your money balance, money operations will be unavailable");
782 }
783 catch (InvalidCastException)
784 {
785 funds = 0;
786 }
787 }
788 else
789 {
790 m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentId,
791 (string) hbinfo["errorMessage"]);
792 aClient.SendAlertMessage((string) hbinfo["errorMessage"]);
793 }
794 }
795
796 SetLocalFundsForAgentID(agentId, funds);
797 SendMoneyBalance(aClient, agentId, aClient.SessionId, UUID.Zero);
798 }
799 else
800 {
801 m_log.Debug("[MONEY]: Got balance request update for agent that is here, but couldn't find which scene.");
802 }
803 }
804 else
805 {
806 m_log.Debug("[MONEY]: Got balance request update for agent that isn't here.");
807 }
808 return funds;
809 }
810
811 public XmlRpcResponse GridMoneyUpdate(XmlRpcRequest request)
812 {
813 m_log.Debug("[MONEY]: Dynamic balance update called.");
814 Hashtable requestData = (Hashtable) request.Params[0];
815
816 if (requestData.ContainsKey("agentId"))
817 {
818 UUID agentId = UUID.Zero;
819
820 UUID.TryParse((string) requestData["agentId"], out agentId);
821 if (agentId != UUID.Zero)
822 {
823 GetRemoteBalance(agentId);
824 }
825 else
826 {
827 m_log.Debug("[MONEY]: invalid agentId specified, dropping.");
828 }
829 }
830 else
831 {
832 m_log.Debug("[MONEY]: no agentId specified, dropping.");
833 }
834 XmlRpcResponse r = new XmlRpcResponse();
835 Hashtable rparms = new Hashtable();
836 rparms["success"] = true;
837
838 r.Value = rparms;
839 return r;
840 }
841
842 /// <summary>
843 /// XMLRPC handler to send alert message and sound to client
844 /// </summary>
845 public XmlRpcResponse UserAlert(XmlRpcRequest request)
846 {
847 XmlRpcResponse ret = new XmlRpcResponse();
848 Hashtable retparam = new Hashtable();
849 Hashtable requestData = (Hashtable) request.Params[0];
850
851 UUID agentId;
852 UUID soundId;
853 UUID regionId;
854
855 UUID.TryParse((string) requestData["agentId"], out agentId);
856 UUID.TryParse((string) requestData["soundId"], out soundId);
857 UUID.TryParse((string) requestData["regionId"], out regionId);
858 string text = (string) requestData["text"];
859 string secret = (string) requestData["secret"];
860
861 Scene userScene = GetSceneByUUID(regionId);
862 if (userScene != null)
863 {
864 if (userScene.RegionInfo.regionSecret == secret)
865 {
866
867 IClientAPI client = LocateClientObject(agentId);
868 if (client != null)
869 {
870
871 if (soundId != UUID.Zero)
872 client.SendPlayAttachedSound(soundId, UUID.Zero, UUID.Zero, 1.0f, 0);
873
874 client.SendBlueBoxMessage(UUID.Zero, "", text);
875
876 retparam.Add("success", true);
877 }
878 else
879 {
880 retparam.Add("success", false);
881 }
882 }
883 else
884 {
885 retparam.Add("success", false);
886 }
887 }
888
889 ret.Value = retparam;
890 return ret;
891 }
892
893 # region Standalone box enablers only
894
895 public XmlRpcResponse quote_func(XmlRpcRequest request)
896 {
897 Hashtable requestData = (Hashtable) request.Params[0];
898 UUID agentId = UUID.Zero;
899 int amount = 0;
900 Hashtable quoteResponse = new Hashtable();
901 XmlRpcResponse returnval = new XmlRpcResponse();
902
903 if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy"))
904 {
905 UUID.TryParse((string) requestData["agentId"], out agentId);
906 try
907 {
908 amount = (Int32) requestData["currencyBuy"];
909 }
910 catch (InvalidCastException)
911 {
912 }
913 Hashtable currencyResponse = new Hashtable();
914 currencyResponse.Add("estimatedCost", 0);
915 currencyResponse.Add("currencyBuy", amount);
916
917 quoteResponse.Add("success", true);
918 quoteResponse.Add("currency", currencyResponse);
919 quoteResponse.Add("confirm", "asdfad9fj39ma9fj");
920
921 returnval.Value = quoteResponse;
922 return returnval;
923 }
924
925
926 quoteResponse.Add("success", false);
927 quoteResponse.Add("errorMessage", "Invalid parameters passed to the quote box");
928 quoteResponse.Add("errorURI", "http://www.opensimulator.org/wiki");
929 returnval.Value = quoteResponse;
930 return returnval;
931 }
932
933 public XmlRpcResponse buy_func(XmlRpcRequest request)
934 {
935 Hashtable requestData = (Hashtable) request.Params[0];
936 UUID agentId = UUID.Zero;
937 int amount = 0;
938 if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy"))
939 {
940 UUID.TryParse((string) requestData["agentId"], out agentId);
941 try
942 {
943 amount = (Int32) requestData["currencyBuy"];
944 }
945 catch (InvalidCastException)
946 {
947 }
948 if (agentId != UUID.Zero)
949 {
950 lock (m_KnownClientFunds)
951 {
952 if (m_KnownClientFunds.ContainsKey(agentId))
953 {
954 m_KnownClientFunds[agentId] += amount;
955 }
956 else
957 {
958 m_KnownClientFunds.Add(agentId, amount);
959 }
960 }
961 IClientAPI client = LocateClientObject(agentId);
962 if (client != null)
963 {
964 SendMoneyBalance(client, agentId, client.SessionId, UUID.Zero);
965 }
966 }
967 }
968 XmlRpcResponse returnval = new XmlRpcResponse();
969 Hashtable returnresp = new Hashtable();
970 returnresp.Add("success", true);
971 returnval.Value = returnresp;
972 return returnval;
973 }
974
975 public XmlRpcResponse preflightBuyLandPrep_func(XmlRpcRequest request)
976 {
977 XmlRpcResponse ret = new XmlRpcResponse();
978 Hashtable retparam = new Hashtable();
979 Hashtable membershiplevels = new Hashtable();
980 ArrayList levels = new ArrayList();
981 Hashtable level = new Hashtable();
982 level.Add("id", "00000000-0000-0000-0000-000000000000");
983 level.Add("description", "some level");
984 levels.Add(level);
985 //membershiplevels.Add("levels",levels);
986
987 Hashtable landuse = new Hashtable();
988 landuse.Add("upgrade", false);
989 landuse.Add("action", "http://invaliddomaininvalid.com/");
990
991 Hashtable currency = new Hashtable();
992 currency.Add("estimatedCost", 0);
993
994 Hashtable membership = new Hashtable();
995 membershiplevels.Add("upgrade", false);
996 membershiplevels.Add("action", "http://invaliddomaininvalid.com/");
997 membershiplevels.Add("levels", membershiplevels);
998
999 retparam.Add("success", true);
1000 retparam.Add("currency", currency);
1001 retparam.Add("membership", membership);
1002 retparam.Add("landuse", landuse);
1003 retparam.Add("confirm", "asdfajsdkfjasdkfjalsdfjasdf");
1004
1005 ret.Value = retparam;
1006
1007 return ret;
1008 }
1009
1010 public XmlRpcResponse landBuy_func(XmlRpcRequest request)
1011 {
1012 XmlRpcResponse ret = new XmlRpcResponse();
1013 Hashtable retparam = new Hashtable();
1014 Hashtable requestData = (Hashtable) request.Params[0];
1015
1016 UUID agentId = UUID.Zero;
1017 int amount = 0;
1018 if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy"))
1019 {
1020 UUID.TryParse((string) requestData["agentId"], out agentId);
1021 try
1022 {
1023 amount = (Int32) requestData["currencyBuy"];
1024 }
1025 catch (InvalidCastException)
1026 {
1027 }
1028 if (agentId != UUID.Zero)
1029 {
1030 lock (m_KnownClientFunds)
1031 {
1032 if (m_KnownClientFunds.ContainsKey(agentId))
1033 {
1034 m_KnownClientFunds[agentId] += amount;
1035 }
1036 else
1037 {
1038 m_KnownClientFunds.Add(agentId, amount);
1039 }
1040 }
1041 IClientAPI client = LocateClientObject(agentId);
1042 if (client != null)
1043 {
1044 SendMoneyBalance(client, agentId, client.SessionId, UUID.Zero);
1045 }
1046 }
1047 }
1048 retparam.Add("success", true);
1049 ret.Value = retparam;
1050
1051 return ret;
1052 }
1053
1054 #endregion
1055
1056 #region local Fund Management
1057
1058 /// <summary>
1059 /// Ensures that the agent accounting data is set up in this instance.
1060 /// </summary>
1061 /// <param name="agentID"></param>
1062 private void CheckExistAndRefreshFunds(UUID agentID)
1063 {
1064 lock (m_KnownClientFunds)
1065 {
1066 if (!m_KnownClientFunds.ContainsKey(agentID))
1067 {
1068 m_KnownClientFunds.Add(agentID, m_stipend);
1069 }
1070 else
1071 {
1072 if (m_KnownClientFunds[agentID] <= m_minFundsBeforeRefresh)
1073 {
1074 m_KnownClientFunds[agentID] = m_stipend;
1075 }
1076 }
1077 }
1078 }
1079
1080 /// <summary>
1081 /// Gets the amount of Funds for an agent
1082 /// </summary>
1083 /// <param name="AgentID"></param>
1084 /// <returns></returns>
1085 private int GetFundsForAgentID(UUID AgentID)
1086 {
1087 int returnfunds = 0;
1088 lock (m_KnownClientFunds)
1089 {
1090 if (m_KnownClientFunds.ContainsKey(AgentID))
1091 {
1092 returnfunds = m_KnownClientFunds[AgentID];
1093 }
1094 else
1095 {
1096 //throw new Exception("Unable to get funds.");
1097 }
1098 }
1099 return returnfunds;
1100 }
1101
1102 private void SetLocalFundsForAgentID(UUID AgentID, int amount)
1103 {
1104 lock (m_KnownClientFunds)
1105 {
1106 if (m_KnownClientFunds.ContainsKey(AgentID))
1107 {
1108 m_KnownClientFunds[AgentID] = amount;
1109 }
1110 else
1111 {
1112 m_KnownClientFunds.Add(AgentID, amount);
1113 }
1114 }
1115 }
1116
1117 #endregion
1118
1119 #region Utility Helpers
1120
1121 /// <summary>
1122 /// Locates a IClientAPI for the client specified
1123 /// </summary>
1124 /// <param name="AgentID"></param>
1125 /// <returns></returns>
1126 private IClientAPI LocateClientObject(UUID AgentID)
1127 {
1128 ScenePresence tPresence = null;
1129 IClientAPI rclient = null;
1130
1131 lock (m_scenel)
1132 {
1133 foreach (Scene _scene in m_scenel.Values)
1134 {
1135 tPresence = _scene.GetScenePresence(AgentID);
1136 if (tPresence != null)
1137 {
1138 if (!tPresence.IsChildAgent)
1139 {
1140 rclient = tPresence.ControllingClient;
1141 }
1142 }
1143 if (rclient != null)
1144 {
1145 return rclient;
1146 }
1147 }
1148 }
1149 return null;
1150 }
1151
1152 private Scene LocateSceneClientIn(UUID AgentId)
1153 {
1154 lock (m_scenel)
1155 {
1156 foreach (Scene _scene in m_scenel.Values)
1157 {
1158 ScenePresence tPresence = _scene.GetScenePresence(AgentId);
1159 if (tPresence != null)
1160 {
1161 if (!tPresence.IsChildAgent)
1162 {
1163 return _scene;
1164 }
1165 }
1166 }
1167 }
1168 return null;
1169 }
1170
1171 /// <summary>
1172 /// Utility function Gets a Random scene in the instance. For when which scene exactly you're doing something with doesn't matter
1173 /// </summary>
1174 /// <returns></returns>
1175 public Scene GetRandomScene()
1176 {
1177 lock (m_scenel)
1178 {
1179 foreach (Scene rs in m_scenel.Values)
1180 return rs;
1181 }
1182 return null;
1183 }
1184
1185 /// <summary>
1186 /// Utility function to get a Scene by RegionID in a module
1187 /// </summary>
1188 /// <param name="RegionID"></param>
1189 /// <returns></returns>
1190 public Scene GetSceneByUUID(UUID RegionID)
1191 {
1192 lock (m_scenel)
1193 {
1194 foreach (Scene rs in m_scenel.Values)
1195 {
1196 if (rs.RegionInfo.originRegionID == RegionID)
1197 {
1198 return rs;
1199 }
1200 }
1201 }
1202 return null;
1203 }
1204
1205 #endregion
1206
1207 #region event Handlers
1208
1209 public void requestPayPrice(IClientAPI client, UUID objectID)
1210 {
1211 Scene scene = LocateSceneClientIn(client.AgentId);
1212 if (scene == null)
1213 return;
1214
1215 SceneObjectPart task = scene.GetSceneObjectPart(objectID);
1216 if (task == null)
1217 return;
1218 SceneObjectGroup group = task.ParentGroup;
1219 SceneObjectPart root = group.RootPart;
1220
1221 client.SendPayPrice(objectID, root.PayPrice);
1222 }
1223
1224 /// <summary>
1225 /// When the client closes the connection we remove their accounting info from memory to free up resources.
1226 /// </summary>
1227 /// <param name="AgentID"></param>
1228 public void ClientClosed(UUID AgentID)
1229 {
1230 lock (m_KnownClientFunds)
1231 {
1232 if (m_keepMoneyAcrossLogins && m_MoneyAddress.Length == 0)
1233 {
1234 }
1235 else
1236 {
1237 m_KnownClientFunds.Remove(AgentID);
1238 }
1239 }
1240 }
1241
1242 /// <summary>
1243 /// Event called Economy Data Request handler.
1244 /// </summary>
1245 /// <param name="agentId"></param>
1246 public void EconomyDataRequestHandler(UUID agentId)
1247 {
1248 IClientAPI user = LocateClientObject(agentId);
1249
1250 if (user != null)
1251 {
1252 user.SendEconomyData(EnergyEfficiency, ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate,
1253 PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor,
1254 PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload,
1255 TeleportMinPrice, TeleportPriceExponent);
1256 }
1257 }
1258
1259 private void ValidateLandBuy(Object osender, EventManager.LandBuyArgs e)
1260 {
1261 if (m_MoneyAddress.Length == 0)
1262 {
1263 lock (m_KnownClientFunds)
1264 {
1265 if (m_KnownClientFunds.ContainsKey(e.agentId))
1266 {
1267 // Does the sender have enough funds to give?
1268 if (m_KnownClientFunds[e.agentId] >= e.parcelPrice)
1269 {
1270 lock (e)
1271 {
1272 e.economyValidated = true;
1273 }
1274 }
1275 }
1276 }
1277 }
1278 else
1279 {
1280 if (GetRemoteBalance(e.agentId) >= e.parcelPrice)
1281 {
1282 lock (e)
1283 {
1284 e.economyValidated = true;
1285 }
1286 }
1287 }
1288 }
1289
1290 private void processLandBuy(Object osender, EventManager.LandBuyArgs e)
1291 {
1292 lock (e)
1293 {
1294 if (e.economyValidated == true && e.transactionID == 0)
1295 {
1296 e.transactionID = Util.UnixTimeSinceEpoch();
1297
1298 if (doMoneyTransfer(e.agentId, e.parcelOwnerID, e.parcelPrice, 0, "Land purchase"))
1299 {
1300 lock (e)
1301 {
1302 e.amountDebited = e.parcelPrice;
1303 }
1304 }
1305 }
1306 }
1307 }
1308
1309 /// <summary>
1310 /// THis method gets called when someone pays someone else as a gift.
1311 /// </summary>
1312 /// <param name="osender"></param>
1313 /// <param name="e"></param>
1314 private void MoneyTransferAction(Object osender, EventManager.MoneyTransferArgs e)
1315 {
1316 IClientAPI sender = null;
1317 IClientAPI receiver = null;
1318
1319 if (m_MoneyAddress.Length > 0) // Handled on server
1320 e.description = String.Empty;
1321
1322 if (e.transactiontype == 5008) // Object gets paid
1323 {
1324 sender = LocateClientObject(e.sender);
1325 if (sender != null)
1326 {
1327 SceneObjectPart part = findPrim(e.receiver);
1328 if (part == null)
1329 return;
1330
1331 string name = resolveAgentName(part.OwnerID);
1332 if (name == String.Empty)
1333 name = "(hippos)";
1334
1335 receiver = LocateClientObject(part.OwnerID);
1336
1337 string description = String.Format("Paid {0} via object {1}", name, e.description);
1338 bool transactionresult = doMoneyTransfer(e.sender, part.OwnerID, e.amount, e.transactiontype, description);
1339
1340 if (transactionresult)
1341 {
1342 ObjectPaid handlerOnObjectPaid = OnObjectPaid;
1343 if (handlerOnObjectPaid != null)
1344 {
1345 handlerOnObjectPaid(e.receiver, e.sender, e.amount);
1346 }
1347 }
1348
1349 if (e.sender != e.receiver)
1350 {
1351 sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(e.sender));
1352 }
1353 if (receiver != null)
1354 {
1355 receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(part.OwnerID));
1356 }
1357 }
1358 return;
1359 }
1360
1361 sender = LocateClientObject(e.sender);
1362 if (sender != null)
1363 {
1364 receiver = LocateClientObject(e.receiver);
1365
1366 bool transactionresult = doMoneyTransfer(e.sender, e.receiver, e.amount, e.transactiontype, e.description);
1367
1368 if (e.sender != e.receiver)
1369 {
1370 if (sender != null)
1371 {
1372 sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(e.sender));
1373 }
1374 }
1375
1376 if (receiver != null)
1377 {
1378 receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(e.receiver));
1379 }
1380 }
1381 else
1382 {
1383 m_log.Warn("[MONEY]: Potential Fraud Warning, got money transfer request for avatar that isn't in this simulator - Details; Sender:" +
1384 e.sender.ToString() + " Receiver: " + e.receiver.ToString() + " Amount: " + e.amount.ToString());
1385 }
1386 }
1387
1388 /// <summary>
1389 /// Event Handler for when a root agent becomes a child agent
1390 /// </summary>
1391 /// <param name="avatar"></param>
1392 private void MakeChildAgent(ScenePresence avatar)
1393 {
1394 lock (m_rootAgents)
1395 {
1396 if (m_rootAgents.ContainsKey(avatar.UUID))
1397 {
1398 if (m_rootAgents[avatar.UUID] == avatar.Scene.RegionInfo.originRegionID)
1399 {
1400 m_rootAgents.Remove(avatar.UUID);
1401// m_log.Debug("[MONEY]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent");
1402 }
1403 }
1404 }
1405 }
1406
1407 /// <summary>
1408 /// Event Handler for when the client logs out.
1409 /// </summary>
1410 /// <param name="AgentId"></param>
1411 private void ClientLoggedOut(UUID AgentId)
1412 {
1413 lock (m_rootAgents)
1414 {
1415 if (m_rootAgents.ContainsKey(AgentId))
1416 {
1417 m_rootAgents.Remove(AgentId);
1418 //m_log.Info("[MONEY]: Removing " + AgentId + ". Agent logged out.");
1419 }
1420 }
1421 }
1422
1423 /// <summary>
1424 /// Call this when the client disconnects.
1425 /// </summary>
1426 /// <param name="client"></param>
1427 public void ClientClosed(IClientAPI client)
1428 {
1429 ClientClosed(client.AgentId);
1430 }
1431
1432 /// <summary>
1433 /// Event Handler for when an Avatar enters one of the parcels in the simulator.
1434 /// </summary>
1435 /// <param name="avatar"></param>
1436 /// <param name="localLandID"></param>
1437 /// <param name="regionID"></param>
1438 private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID)
1439 {
1440 lock (m_rootAgents)
1441 {
1442 if (m_rootAgents.ContainsKey(avatar.UUID))
1443 {
1444 if (avatar.Scene.RegionInfo.originRegionID != m_rootAgents[avatar.UUID])
1445 {
1446 m_rootAgents[avatar.UUID] = avatar.Scene.RegionInfo.originRegionID;
1447
1448
1449 //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + ".");
1450 // Claim User! my user! Mine mine mine!
1451 if (m_MoneyAddress.Length > 0)
1452 {
1453 Scene RegionItem = GetSceneByUUID(regionID);
1454 if (RegionItem != null)
1455 {
1456 Hashtable hresult =
1457 claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret);
1458 if ((bool)hresult["success"] == true)
1459 {
1460 int funds = 0;
1461 try
1462 {
1463 funds = (Int32)hresult["funds"];
1464 }
1465 catch (InvalidCastException)
1466 {
1467 }
1468 SetLocalFundsForAgentID(avatar.UUID, funds);
1469 }
1470 else
1471 {
1472 avatar.ControllingClient.SendAgentAlertMessage((string)hresult["errorMessage"], true);
1473 }
1474 }
1475 }
1476 }
1477 else
1478 {
1479 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
1480 if ((obj.landData.Flags & (uint)Parcel.ParcelFlags.AllowDamage) != 0)
1481 {
1482 avatar.Invulnerable = false;
1483 }
1484 else
1485 {
1486 avatar.Invulnerable = true;
1487 }
1488 }
1489 }
1490 else
1491 {
1492 lock (m_rootAgents)
1493 {
1494 m_rootAgents.Add(avatar.UUID, avatar.Scene.RegionInfo.originRegionID);
1495 }
1496 if (m_MoneyAddress.Length > 0)
1497 {
1498 Scene RegionItem = GetSceneByUUID(regionID);
1499 if (RegionItem != null)
1500 {
1501 Hashtable hresult = claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret);
1502 if ((bool) hresult["success"] == true)
1503 {
1504 int funds = 0;
1505 try
1506 {
1507 funds = (Int32) hresult["funds"];
1508 }
1509 catch (InvalidCastException)
1510 {
1511 }
1512 SetLocalFundsForAgentID(avatar.UUID, funds);
1513 }
1514 else
1515 {
1516 avatar.ControllingClient.SendAgentAlertMessage((string) hresult["errorMessage"], true);
1517 }
1518 }
1519 }
1520
1521 //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + ".");
1522 }
1523 }
1524 //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString());
1525 }
1526
1527 public int GetBalance(IClientAPI client)
1528 {
1529 GetClientFunds(client);
1530
1531 lock (m_KnownClientFunds)
1532 {
1533 if (!m_KnownClientFunds.ContainsKey(client.AgentId))
1534 return 0;
1535
1536 return m_KnownClientFunds[client.AgentId];
1537 }
1538 }
1539
1540 // Please do not refactor these to be just one method
1541 // Existing implementations need the distinction
1542 //
1543 public bool UploadCovered(IClientAPI client)
1544 {
1545 return AmountCovered(client, PriceUpload);
1546 }
1547
1548 public bool GroupCreationCovered(IClientAPI client)
1549 {
1550 return AmountCovered(client, PriceGroupCreate);
1551 }
1552
1553 public bool AmountCovered(IClientAPI client, int amount)
1554 {
1555 if (GetBalance(client) < amount)
1556 return false;
1557 return true;
1558 }
1559
1560 #endregion
1561
1562 public void ObjectBuy(IClientAPI remoteClient, UUID agentID,
1563 UUID sessionID, UUID groupID, UUID categoryID,
1564 uint localID, byte saleType, int salePrice)
1565 {
1566 GetClientFunds(remoteClient);
1567
1568 if (!m_KnownClientFunds.ContainsKey(remoteClient.AgentId))
1569 {
1570 remoteClient.SendAgentAlertMessage("Unable to buy now. Your account balance was not found.", false);
1571 return;
1572 }
1573
1574 int funds = m_KnownClientFunds[remoteClient.AgentId];
1575
1576 if (salePrice != 0 && funds < salePrice)
1577 {
1578 remoteClient.SendAgentAlertMessage("Unable to buy now. You don't have sufficient funds.", false);
1579 return;
1580 }
1581
1582 Scene s = LocateSceneClientIn(remoteClient.AgentId);
1583
1584 SceneObjectPart part = s.GetSceneObjectPart(localID);
1585 if (part == null)
1586 {
1587 remoteClient.SendAgentAlertMessage("Unable to buy now. The object was not found.", false);
1588 return;
1589 }
1590
1591 if (s.PerformObjectBuy(remoteClient, categoryID, localID, saleType))
1592 doMoneyTransfer(remoteClient.AgentId, part.OwnerID, salePrice, 5000, "Object buy");
1593 }
1594 }
1595
1596 public enum TransactionType : int
1597 {
1598 SystemGenerated = 0,
1599 RegionMoneyRequest = 1,
1600 Gift = 2,
1601 Purchase = 3
1602 }
1603
1604
1605}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Dialog/DialogModule.cs
deleted file mode 100644
index d3ac2c0..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Dialog/DialogModule.cs
+++ /dev/null
@@ -1,143 +0,0 @@
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 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 */
27
28using System.Collections.Generic;
29using System.Reflection;
30using log4net;
31using Nini.Config;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36
37namespace OpenSim.Region.Environment.Modules.Avatar.Dialog
38{
39 public class DialogModule : IRegionModule, IDialogModule
40 {
41 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 protected Scene m_scene;
44
45 public void Initialise(Scene scene, IConfigSource source)
46 {
47 m_scene = scene;
48 m_scene.RegisterModuleInterface<IDialogModule>(this);
49 }
50
51 public void PostInitialise() {}
52 public void Close() {}
53 public string Name { get { return "Dialog Module"; } }
54 public bool IsSharedModule { get { return false; } }
55
56 public void SendAlertToUser(IClientAPI client, string message)
57 {
58 SendAlertToUser(client, message, false);
59 }
60
61 public void SendAlertToUser(IClientAPI client, string message, bool modal)
62 {
63 client.SendAgentAlertMessage(message, modal);
64 }
65
66 public void SendAlertToUser(UUID agentID, string message)
67 {
68 SendAlertToUser(agentID, message, false);
69 }
70
71 public void SendAlertToUser(UUID agentID, string message, bool modal)
72 {
73 ScenePresence sp = m_scene.GetScenePresence(agentID);
74
75 if (sp != null)
76 sp.ControllingClient.SendAgentAlertMessage(message, modal);
77 }
78
79 public void SendAlertToUser(string firstName, string lastName, string message, bool modal)
80 {
81 List<ScenePresence> presenceList = m_scene.GetScenePresences();
82
83 foreach (ScenePresence presence in presenceList)
84 {
85 if (presence.Firstname == firstName && presence.Lastname == lastName)
86 {
87 presence.ControllingClient.SendAgentAlertMessage(message, modal);
88 break;
89 }
90 }
91 }
92
93 public void SendGeneralAlert(string message)
94 {
95 List<ScenePresence> presenceList = m_scene.GetScenePresences();
96
97 foreach (ScenePresence presence in presenceList)
98 {
99 if (!presence.IsChildAgent)
100 presence.ControllingClient.SendAlertMessage(message);
101 }
102 }
103
104 public void SendDialogToUser(
105 UUID avatarID, string objectName, UUID objectID, UUID ownerID,
106 string message, UUID textureID, int ch, string[] buttonlabels)
107 {
108 ScenePresence sp = m_scene.GetScenePresence(avatarID);
109
110 if (sp != null)
111 sp.ControllingClient.SendDialog(objectName, objectID, ownerID, message, textureID, ch, buttonlabels);
112 }
113
114 public void SendUrlToUser(
115 UUID avatarID, string objectName, UUID objectID, UUID ownerID, bool groupOwned, string message, string url)
116 {
117 ScenePresence sp = m_scene.GetScenePresence(avatarID);
118
119 if (sp != null)
120 sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url);
121 }
122
123 public void SendNotificationToUsersInEstate(
124 UUID fromAvatarID, string fromAvatarName, string message)
125 {
126 // TODO: This does not yet do what it says on the tin - it only sends the message to users in the same
127 // region as the sending avatar.
128 SendNotificationToUsersInRegion(fromAvatarID, fromAvatarName, message);
129 }
130
131 public void SendNotificationToUsersInRegion(
132 UUID fromAvatarID, string fromAvatarName, string message)
133 {
134 List<ScenePresence> presenceList = m_scene.GetScenePresences();
135
136 foreach (ScenePresence presence in presenceList)
137 {
138 if (!presence.IsChildAgent)
139 presence.ControllingClient.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message);
140 }
141 }
142 }
143}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
deleted file mode 100644
index 0ed962e..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
+++ /dev/null
@@ -1,1003 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenMetaverse;
33using log4net;
34using Nini.Config;
35using Nwc.XmlRpc;
36using OpenSim.Framework;
37using OpenSim.Framework.Communications.Cache;
38using OpenSim.Framework.Servers;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.Environment.Modules.Avatar.Friends
43{
44 /*
45 This module handles adding/removing friends, and the the presence
46 notification process for login/logoff of friends.
47
48 The presence notification works as follows:
49 - After the user initially connects to a region (so we now have a UDP
50 connection to work with), this module fetches the friends of user
51 (those are cached), their on-/offline status, and info about the
52 region they are in from the MessageServer.
53 - (*) It then informs the user about the on-/offline status of her friends.
54 - It then informs all online friends currently on this region-server about
55 user's new online status (this will save some network traffic, as local
56 messages don't have to be transferred inter-region, and it will be all
57 that has to be done in Standalone Mode).
58 - For the rest of the online friends (those not on this region-server),
59 this module uses the provided region-information to map users to
60 regions, and sends one notification to every region containing the
61 friends to inform on that server.
62 - The region-server will handle that in the following way:
63 - If it finds the friend, it informs her about the user being online.
64 - If it doesn't find the friend (maybe she TPed away in the meantime),
65 it stores that information.
66 - After it processed all friends, it returns the list of friends it
67 couldn't find.
68 - If this list isn't empty, the FriendsModule re-requests information
69 about those online friends that have been missed and starts at (*)
70 again until all friends have been found, or until it tried 3 times
71 (to prevent endless loops due to some uncaught error).
72
73 NOTE: Online/Offline notifications don't need to be sent on region change.
74
75 We implement two XMLRpc handlers here, handling all the inter-region things
76 we have to handle:
77 - On-/Offline-Notifications (bulk)
78 - Terminate Friendship messages (single)
79 */
80
81 public class FriendsModule : IRegionModule, IFriendsModule
82 {
83 private class Transaction
84 {
85 public UUID agentID;
86 public string agentName;
87 public uint count;
88
89 public Transaction(UUID agentID, string agentName)
90 {
91 this.agentID = agentID;
92 this.agentName = agentName;
93 this.count = 1;
94 }
95 }
96
97 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
98
99 private Cache m_friendLists = new Cache(CacheFlags.AllowUpdate);
100
101 private Dictionary<UUID, ulong> m_rootAgents = new Dictionary<UUID, ulong>();
102
103 private Dictionary<UUID, UUID> m_pendingCallingcardRequests = new Dictionary<UUID,UUID>();
104
105 private Scene m_initialScene; // saves a lookup if we don't have a specific scene
106 private Dictionary<ulong, Scene> m_scenes = new Dictionary<ulong,Scene>();
107 private IMessageTransferModule m_TransferModule = null;
108
109 #region IRegionModule Members
110
111 public void Initialise(Scene scene, IConfigSource config)
112 {
113 lock (m_scenes)
114 {
115 if (m_scenes.Count == 0)
116 {
117 scene.CommsManager.HttpServer.AddXmlRPCHandler("presence_update_bulk", processPresenceUpdateBulk);
118 scene.CommsManager.HttpServer.AddXmlRPCHandler("terminate_friend", processTerminateFriend);
119 m_friendLists.DefaultTTL = new TimeSpan(1, 0, 0); // store entries for one hour max
120 m_initialScene = scene;
121 }
122
123 if (!m_scenes.ContainsKey(scene.RegionInfo.RegionHandle))
124 m_scenes[scene.RegionInfo.RegionHandle] = scene;
125 }
126
127 scene.RegisterModuleInterface<IFriendsModule>(this);
128
129 scene.EventManager.OnNewClient += OnNewClient;
130 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
131 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
132 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
133 scene.EventManager.OnClientClosed += ClientClosed;
134 }
135
136 public void PostInitialise()
137 {
138 if (m_scenes.Count > 0)
139 {
140 m_TransferModule = m_initialScene.RequestModuleInterface<IMessageTransferModule>();
141 }
142 if (m_TransferModule == null)
143 m_log.Error("[FRIENDS]: Unable to find a message transfer module, friendship offers will not work");
144 }
145
146 public void Close()
147 {
148 }
149
150 public string Name
151 {
152 get { return "FriendsModule"; }
153 }
154
155 public bool IsSharedModule
156 {
157 get { return true; }
158 }
159
160 #endregion
161
162 /// <summary>
163 /// Receive presence information changes about clients in other regions.
164 /// </summary>
165 /// <param name="req"></param>
166 /// <returns></returns>
167 public XmlRpcResponse processPresenceUpdateBulk(XmlRpcRequest req)
168 {
169 Hashtable requestData = (Hashtable)req.Params[0];
170
171 List<UUID> friendsNotHere = new List<UUID>();
172
173 // this is called with the expectation that all the friends in the request are on this region-server.
174 // But as some time passed since we checked (on the other region-server, via the MessagingServer),
175 // some of the friends might have teleported away.
176 // Actually, even now, between this line and the sending below, some people could TP away. So,
177 // we'll have to lock the m_rootAgents list for the duration to prevent/delay that.
178 lock (m_rootAgents)
179 {
180 List<ScenePresence> friendsHere = new List<ScenePresence>();
181
182 try
183 {
184 UUID agentID = new UUID((string)requestData["agentID"]);
185 bool agentOnline = (bool)requestData["agentOnline"];
186 int count = (int)requestData["friendCount"];
187 for (int i = 0; i < count; ++i)
188 {
189 UUID uuid;
190 if (UUID.TryParse((string)requestData["friendID_" + i], out uuid))
191 {
192 if (m_rootAgents.ContainsKey(uuid)) friendsHere.Add(GetRootPresenceFromAgentID(uuid));
193 else friendsNotHere.Add(uuid);
194 }
195 }
196
197 // now send, as long as they are still here...
198 UUID[] agentUUID = new UUID[] { agentID };
199 if (agentOnline)
200 {
201 foreach (ScenePresence agent in friendsHere)
202 {
203 agent.ControllingClient.SendAgentOnline(agentUUID);
204 }
205 }
206 else
207 {
208 foreach (ScenePresence agent in friendsHere)
209 {
210 agent.ControllingClient.SendAgentOffline(agentUUID);
211 }
212 }
213 }
214 catch(Exception e)
215 {
216 m_log.Warn("[FRIENDS]: Got exception while parsing presence_update_bulk request:", e);
217 }
218 }
219
220 // no need to lock anymore; if TPs happen now, worst case is that we have an additional agent in this region,
221 // which should be caught on the next iteration...
222 Hashtable result = new Hashtable();
223 int idx = 0;
224 foreach (UUID uuid in friendsNotHere)
225 {
226 result["friendID_" + idx++] = uuid.ToString();
227 }
228 result["friendCount"] = idx;
229
230 XmlRpcResponse response = new XmlRpcResponse();
231 response.Value = result;
232
233 return response;
234 }
235
236 public XmlRpcResponse processTerminateFriend(XmlRpcRequest req)
237 {
238 Hashtable requestData = (Hashtable)req.Params[0];
239
240 bool success = false;
241
242 UUID agentID;
243 UUID friendID;
244 if (requestData.ContainsKey("agentID") && UUID.TryParse((string)requestData["agentID"], out agentID) &&
245 requestData.ContainsKey("friendID") && UUID.TryParse((string)requestData["friendID"], out friendID))
246 {
247 // try to find it and if it is there, prevent it to vanish before we sent the message
248 lock (m_rootAgents)
249 {
250 if (m_rootAgents.ContainsKey(agentID))
251 {
252 m_log.DebugFormat("[FRIEND]: Sending terminate friend {0} to agent {1}", friendID, agentID);
253 GetRootPresenceFromAgentID(agentID).ControllingClient.SendTerminateFriend(friendID);
254 success = true;
255 }
256 }
257 }
258
259 // return whether we were successful
260 Hashtable result = new Hashtable();
261 result["success"] = success;
262
263 XmlRpcResponse response = new XmlRpcResponse();
264 response.Value = result;
265 return response;
266 }
267
268 private void OnNewClient(IClientAPI client)
269 {
270 // All friends establishment protocol goes over instant message
271 // There's no way to send a message from the sim
272 // to a user to 'add a friend' without causing dialog box spam
273
274 // Subscribe to instant messages
275 client.OnInstantMessage += OnInstantMessage;
276
277 // Friend list management
278 client.OnApproveFriendRequest += OnApproveFriendRequest;
279 client.OnDenyFriendRequest += OnDenyFriendRequest;
280 client.OnTerminateFriendship += OnTerminateFriendship;
281
282 // ... calling card handling...
283 client.OnOfferCallingCard += OnOfferCallingCard;
284 client.OnAcceptCallingCard += OnAcceptCallingCard;
285 client.OnDeclineCallingCard += OnDeclineCallingCard;
286
287 // we need this one exactly once per agent session (see comments in the handler below)
288 client.OnEconomyDataRequest += OnEconomyDataRequest;
289
290 // if it leaves, we want to know, too
291 client.OnLogout += OnLogout;
292 }
293
294 private void ClientClosed(UUID AgentId)
295 {
296 // agent's client was closed. As we handle logout in OnLogout, this here has only to handle
297 // TPing away (root agent is closed) or TPing/crossing in a region far enough away (client
298 // agent is closed).
299 // NOTE: In general, this doesn't mean that the agent logged out, just that it isn't around
300 // in one of the regions here anymore.
301 lock (m_rootAgents)
302 {
303 if (m_rootAgents.ContainsKey(AgentId))
304 {
305 m_rootAgents.Remove(AgentId);
306 }
307 }
308 }
309
310 private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID)
311 {
312 lock (m_rootAgents)
313 {
314 m_rootAgents[avatar.UUID] = avatar.RegionHandle;
315 // Claim User! my user! Mine mine mine!
316 }
317 }
318
319 private void MakeChildAgent(ScenePresence avatar)
320 {
321 lock (m_rootAgents)
322 {
323 if (m_rootAgents.ContainsKey(avatar.UUID))
324 {
325 // only delete if the region matches. As this is a shared module, the avatar could be
326 // root agent in another region on this server.
327 if (m_rootAgents[avatar.UUID] == avatar.RegionHandle)
328 {
329 m_rootAgents.Remove(avatar.UUID);
330// m_log.Debug("[FRIEND]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent");
331 }
332 }
333 }
334 }
335
336 private ScenePresence GetRootPresenceFromAgentID(UUID AgentID)
337 {
338 ScenePresence returnAgent = null;
339 lock (m_scenes)
340 {
341 ScenePresence queryagent = null;
342 foreach (Scene scene in m_scenes.Values)
343 {
344 queryagent = scene.GetScenePresence(AgentID);
345 if (queryagent != null)
346 {
347 if (!queryagent.IsChildAgent)
348 {
349 returnAgent = queryagent;
350 break;
351 }
352 }
353 }
354 }
355 return returnAgent;
356 }
357
358 private ScenePresence GetAnyPresenceFromAgentID(UUID AgentID)
359 {
360 ScenePresence returnAgent = null;
361 lock (m_scenes)
362 {
363 ScenePresence queryagent = null;
364 foreach (Scene scene in m_scenes.Values)
365 {
366 queryagent = scene.GetScenePresence(AgentID);
367 if (queryagent != null)
368 {
369 returnAgent = queryagent;
370 break;
371 }
372 }
373 }
374 return returnAgent;
375 }
376
377 public void OfferFriendship(UUID fromUserId, IClientAPI toUserClient, string offerMessage)
378 {
379 CachedUserInfo userInfo = m_initialScene.CommsManager.UserProfileCacheService.GetUserDetails(fromUserId);
380
381 if (userInfo != null)
382 {
383 GridInstantMessage msg = new GridInstantMessage(
384 toUserClient.Scene, fromUserId, userInfo.UserProfile.Name, toUserClient.AgentId,
385 (byte)InstantMessageDialog.FriendshipOffered, offerMessage, false, Vector3.Zero);
386
387 FriendshipOffered(msg);
388 }
389 else
390 {
391 m_log.ErrorFormat("[FRIENDS]: No user found for id {0} in OfferFriendship()", fromUserId);
392 }
393 }
394
395 #region FriendRequestHandling
396
397 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
398 {
399 // Friend Requests go by Instant Message.. using the dialog param
400 // https://wiki.secondlife.com/wiki/ImprovedInstantMessage
401
402 if (im.dialog == (byte)InstantMessageDialog.FriendshipOffered) // 38
403 {
404 // fromAgentName is the *destination* name (the friend we offer friendship to)
405 ScenePresence initiator = GetAnyPresenceFromAgentID(new UUID(im.fromAgentID));
406 im.fromAgentName = initiator != null ? initiator.Name : "(hippo)";
407
408 FriendshipOffered(im);
409 }
410 else if (im.dialog == (byte)InstantMessageDialog.FriendshipAccepted) // 39
411 {
412 FriendshipAccepted(client, im);
413 }
414 else if (im.dialog == (byte)InstantMessageDialog.FriendshipDeclined) // 40
415 {
416 FriendshipDeclined(client, im);
417 }
418 }
419
420 /// <summary>
421 /// Invoked when a user offers a friendship.
422 /// </summary>
423 ///
424 /// <param name="im"></param>
425 /// <param name="client"></param>
426 private void FriendshipOffered(GridInstantMessage im)
427 {
428 // this is triggered by the initiating agent:
429 // A local agent offers friendship to some possibly remote friend.
430 // A IM is triggered, processed here and sent to the friend (possibly in a remote region).
431
432 m_log.DebugFormat("[FRIEND]: Offer(38) - From: {0}, FromName: {1} To: {2}, Session: {3}, Message: {4}, Offline {5}",
433 im.fromAgentID, im.fromAgentName, im.toAgentID, im.imSessionID, im.message, im.offline);
434
435 // 1.20 protocol sends an UUID in the message field, instead of the friendship offer text.
436 // For interoperability, we have to clear that
437 if (Util.isUUID(im.message)) im.message = "";
438
439 // be sneeky and use the initiator-UUID as transactionID. This means we can be stateless.
440 // we have to look up the agent name on friendship-approval, though.
441 im.imSessionID = im.fromAgentID;
442
443 if (m_TransferModule != null)
444 {
445 // Send it to whoever is the destination.
446 // If new friend is local, it will send an IM to the viewer.
447 // If new friend is remote, it will cause a OnGridInstantMessage on the remote server
448 m_TransferModule.SendInstantMessage(
449 im,
450 delegate(bool success)
451 {
452 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
453 }
454 );
455 }
456 }
457
458 /// <summary>
459 /// Invoked when a user accepts a friendship offer.
460 /// </summary>
461 /// <param name="im"></param>
462 /// <param name="client"></param>
463 private void FriendshipAccepted(IClientAPI client, GridInstantMessage im)
464 {
465 m_log.DebugFormat("[FRIEND]: 39 - from client {0}, agent {2} {3}, imsession {4} to {5}: {6} (dialog {7})",
466 client.AgentId, im.fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog);
467 }
468
469 /// <summary>
470 /// Invoked when a user declines a friendship offer.
471 /// </summary>
472 /// May not currently be used - see OnDenyFriendRequest() instead
473 /// <param name="im"></param>
474 /// <param name="client"></param>
475 private void FriendshipDeclined(IClientAPI client, GridInstantMessage im)
476 {
477 UUID fromAgentID = new UUID(im.fromAgentID);
478 UUID toAgentID = new UUID(im.toAgentID);
479
480 // declining the friendship offer causes a type 40 IM being sent to the (possibly remote) initiator
481 // toAgentID is initiator, fromAgentID declined friendship
482 m_log.DebugFormat("[FRIEND]: 40 - from client {0}, agent {1} {2}, imsession {3} to {4}: {5} (dialog {6})",
483 client != null ? client.AgentId.ToString() : "<null>",
484 fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog);
485
486 // Send the decline to whoever is the destination.
487 GridInstantMessage msg
488 = new GridInstantMessage(
489 client.Scene, fromAgentID, client.Name, toAgentID,
490 im.dialog, im.message, im.offline != 0, im.Position);
491
492 // If new friend is local, it will send an IM to the viewer.
493 // If new friend is remote, it will cause a OnGridInstantMessage on the remote server
494 m_TransferModule.SendInstantMessage(msg,
495 delegate(bool success) {
496 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
497 }
498 );
499 }
500
501 private void OnGridInstantMessage(GridInstantMessage msg)
502 {
503 // This event won't be raised unless we have that agent,
504 // so we can depend on the above not trying to send
505 // via grid again
506 m_log.DebugFormat("[FRIEND]: Got GridIM from {0}, to {1}, imSession {2}, message {3}, dialog {4}",
507 msg.fromAgentID, msg.toAgentID, msg.imSessionID, msg.message, msg.dialog);
508
509 if (msg.dialog == (byte)InstantMessageDialog.FriendshipOffered ||
510 msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted ||
511 msg.dialog == (byte)InstantMessageDialog.FriendshipDeclined)
512 {
513 // this should succeed as we *know* the root agent is here.
514 m_TransferModule.SendInstantMessage(msg,
515 delegate(bool success) {
516 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
517 }
518 );
519 }
520
521 if (msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted)
522 {
523 // for accept friendship, we have to do a bit more
524 ApproveFriendship(new UUID(msg.fromAgentID), new UUID(msg.toAgentID), msg.fromAgentName);
525 }
526 }
527
528 private void ApproveFriendship(UUID fromAgentID, UUID toAgentID, string fromName)
529 {
530 m_log.DebugFormat("[FRIEND]: Approve friendship from {0} (ID: {1}) to {2}",
531 fromAgentID, fromName, toAgentID);
532
533 // a new friend was added in the initiator's and friend's data, so the cache entries are wrong now.
534 lock (m_friendLists)
535 {
536 m_friendLists.Invalidate(fromAgentID);
537 m_friendLists.Invalidate(toAgentID);
538 }
539
540 // now send presence update and add a calling card for the new friend
541
542 ScenePresence initiator = GetAnyPresenceFromAgentID(toAgentID);
543 if (initiator == null)
544 {
545 // quite wrong. Shouldn't happen.
546 m_log.WarnFormat("[FRIEND]: Coudn't find initiator of friend request {0}", toAgentID);
547 return;
548 }
549
550 m_log.DebugFormat("[FRIEND]: Tell {0} that {1} is online",
551 initiator.Name, fromName);
552 // tell initiator that friend is online
553 initiator.ControllingClient.SendAgentOnline(new UUID[] { fromAgentID });
554
555 // find the folder for the friend...
556 InventoryFolderImpl folder =
557 initiator.Scene.CommsManager.UserProfileCacheService.GetUserDetails(toAgentID).FindFolderForType((int)InventoryType.CallingCard);
558 if (folder != null)
559 {
560 // ... and add the calling card
561 CreateCallingCard(initiator.ControllingClient, fromAgentID, folder.ID, fromName);
562 }
563 }
564
565 private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
566 {
567 m_log.DebugFormat("[FRIEND]: Got approve friendship from {0} {1}, agentID {2}, tid {3}",
568 client.Name, client.AgentId, agentID, friendID);
569
570 // store the new friend persistently for both avatars
571 m_initialScene.StoreAddFriendship(friendID, agentID, (uint) FriendRights.CanSeeOnline);
572
573 // The cache entries aren't valid anymore either, as we just added a friend to both sides.
574 lock (m_friendLists)
575 {
576 m_friendLists.Invalidate(agentID);
577 m_friendLists.Invalidate(friendID);
578 }
579
580 // if it's a local friend, we don't have to do the lookup
581 ScenePresence friendPresence = GetAnyPresenceFromAgentID(friendID);
582
583 if (friendPresence != null)
584 {
585 m_log.Debug("[FRIEND]: Local agent detected.");
586
587 // create calling card
588 CreateCallingCard(client, friendID, callingCardFolders[0], friendPresence.Name);
589
590 // local message means OnGridInstantMessage won't be triggered, so do the work here.
591 friendPresence.ControllingClient.SendInstantMessage(agentID, agentID.ToString(), friendID, client.Name,
592 (byte)InstantMessageDialog.FriendshipAccepted,
593 (uint)Util.UnixTimeSinceEpoch());
594 ApproveFriendship(agentID, friendID, client.Name);
595 }
596 else
597 {
598 m_log.Debug("[FRIEND]: Remote agent detected.");
599
600 // fetch the friend's name for the calling card.
601 CachedUserInfo info = m_initialScene.CommsManager.UserProfileCacheService.GetUserDetails(friendID);
602
603 // create calling card
604 CreateCallingCard(client, friendID, callingCardFolders[0],
605 info.UserProfile.FirstName + " " + info.UserProfile.SurName);
606
607 // Compose (remote) response to friend.
608 GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID,
609 (byte)InstantMessageDialog.FriendshipAccepted,
610 agentID.ToString(), false, Vector3.Zero);
611 if (m_TransferModule != null)
612 {
613 m_TransferModule.SendInstantMessage(msg,
614 delegate(bool success) {
615 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
616 }
617 );
618 }
619 }
620
621 // tell client that new friend is online
622 client.SendAgentOnline(new UUID[] { friendID });
623 }
624
625 private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
626 {
627 m_log.DebugFormat("[FRIEND]: Got deny friendship from {0} {1}, agentID {2}, tid {3}",
628 client.Name, client.AgentId, agentID, friendID);
629
630 // Compose response to other agent.
631 GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID,
632 (byte)InstantMessageDialog.FriendshipDeclined,
633 agentID.ToString(), false, Vector3.Zero);
634 // send decline to initiator
635 if (m_TransferModule != null)
636 {
637 m_TransferModule.SendInstantMessage(msg,
638 delegate(bool success) {
639 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
640 }
641 );
642 }
643 }
644
645 private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID)
646 {
647 // client.AgentId == agentID!
648
649 // this removes the friends from the stored friendlists. After the next login, they will be gone...
650 m_initialScene.StoreRemoveFriendship(agentID, exfriendID);
651
652 // ... now tell the two involved clients that they aren't friends anymore.
653
654 // I don't know why we have to tell <agent>, as this was caused by her, but that's how it works in SL...
655 client.SendTerminateFriend(exfriendID);
656
657 // now send the friend, if online
658 ScenePresence presence = GetAnyPresenceFromAgentID(exfriendID);
659 if (presence != null)
660 {
661 m_log.DebugFormat("[FRIEND]: Sending terminate friend {0} to agent {1}", agentID, exfriendID);
662 presence.ControllingClient.SendTerminateFriend(agentID);
663 }
664 else
665 {
666 // retry 3 times, in case the agent TPed from the last known region...
667 for (int retry = 0; retry < 3; ++retry)
668 {
669 // wasn't sent, so ex-friend wasn't around on this region-server. Fetch info and try to send
670 UserAgentData data = m_initialScene.CommsManager.UserService.GetAgentByUUID(exfriendID);
671
672 if (null == data)
673 break;
674
675 if (!data.AgentOnline)
676 {
677 m_log.DebugFormat("[FRIEND]: {0} is offline, so not sending TerminateFriend", exfriendID);
678 break; // if ex-friend isn't online, we don't need to send
679 }
680
681 m_log.DebugFormat("[FRIEND]: Sending remote terminate friend {0} to agent {1}@{2}",
682 agentID, exfriendID, data.Handle);
683
684 // try to send to foreign region, retry if it fails (friend TPed away, for example)
685 if (m_initialScene.TriggerTerminateFriend(data.Handle, exfriendID, agentID)) break;
686 }
687 }
688
689 // clean up cache: FriendList is wrong now...
690 lock (m_friendLists)
691 {
692 m_friendLists.Invalidate(agentID);
693 m_friendLists.Invalidate(exfriendID);
694 }
695 }
696
697 #endregion
698
699 #region CallingCards
700
701 private void OnOfferCallingCard(IClientAPI client, UUID destID, UUID transactionID)
702 {
703 m_log.DebugFormat("[CALLING CARD]: got offer from {0} for {1}, transaction {2}",
704 client.AgentId, destID, transactionID);
705 // This might be slightly wrong. On a multi-region server, we might get the child-agent instead of the root-agent
706 // (or the root instead of the child)
707 ScenePresence destAgent = GetAnyPresenceFromAgentID(destID);
708 if (destAgent == null)
709 {
710 client.SendAlertMessage("The person you have offered a card to can't be found anymore.");
711 return;
712 }
713
714 lock (m_pendingCallingcardRequests)
715 {
716 m_pendingCallingcardRequests[transactionID] = client.AgentId;
717 }
718 // inform the destination agent about the offer
719 destAgent.ControllingClient.SendOfferCallingCard(client.AgentId, transactionID);
720 }
721
722 private void CreateCallingCard(IClientAPI client, UUID creator, UUID folder, string name)
723 {
724 InventoryItemBase item = new InventoryItemBase();
725 item.AssetID = UUID.Zero;
726 item.AssetType = (int)AssetType.CallingCard;
727 item.BasePermissions = (uint)PermissionMask.Copy;
728 item.CreationDate = Util.UnixTimeSinceEpoch();
729 item.Creator = creator;
730 item.CurrentPermissions = item.BasePermissions;
731 item.Description = "";
732 item.EveryOnePermissions = (uint)PermissionMask.None;
733 item.Flags = 0;
734 item.Folder = folder;
735 item.GroupID = UUID.Zero;
736 item.GroupOwned = false;
737 item.ID = UUID.Random();
738 item.InvType = (int)InventoryType.CallingCard;
739 item.Name = name;
740 item.NextPermissions = item.EveryOnePermissions;
741 item.Owner = client.AgentId;
742 item.SalePrice = 10;
743 item.SaleType = (byte)SaleType.Not;
744 ((Scene)client.Scene).AddInventoryItem(client, item);
745 }
746
747 private void OnAcceptCallingCard(IClientAPI client, UUID transactionID, UUID folderID)
748 {
749 m_log.DebugFormat("[CALLING CARD]: User {0} ({1} {2}) accepted tid {3}, folder {4}",
750 client.AgentId,
751 client.FirstName, client.LastName,
752 transactionID, folderID);
753 UUID destID;
754 lock (m_pendingCallingcardRequests)
755 {
756 if (!m_pendingCallingcardRequests.TryGetValue(transactionID, out destID))
757 {
758 m_log.WarnFormat("[CALLING CARD]: Got a AcceptCallingCard from {0} without an offer before.",
759 client.Name);
760 return;
761 }
762 // else found pending calling card request with that transaction.
763 m_pendingCallingcardRequests.Remove(transactionID);
764 }
765
766
767 ScenePresence destAgent = GetAnyPresenceFromAgentID(destID);
768 // inform sender of the card that destination declined the offer
769 if (destAgent != null) destAgent.ControllingClient.SendAcceptCallingCard(transactionID);
770
771 // put a calling card into the inventory of receiver
772 CreateCallingCard(client, destID, folderID, destAgent.Name);
773 }
774
775 private void OnDeclineCallingCard(IClientAPI client, UUID transactionID)
776 {
777 m_log.DebugFormat("[CALLING CARD]: User {0} (ID:{1}) declined card, tid {2}",
778 client.Name, client.AgentId, transactionID);
779 UUID destID;
780 lock (m_pendingCallingcardRequests)
781 {
782 if (!m_pendingCallingcardRequests.TryGetValue(transactionID, out destID))
783 {
784 m_log.WarnFormat("[CALLING CARD]: Got a AcceptCallingCard from {0} without an offer before.",
785 client.Name);
786 return;
787 }
788 // else found pending calling card request with that transaction.
789 m_pendingCallingcardRequests.Remove(transactionID);
790 }
791
792 ScenePresence destAgent = GetAnyPresenceFromAgentID(destID);
793 // inform sender of the card that destination declined the offer
794 if (destAgent != null) destAgent.ControllingClient.SendDeclineCallingCard(transactionID);
795 }
796
797 /// <summary>
798 /// Send presence information about a client to other clients in both this region and others.
799 /// </summary>
800 /// <param name="client"></param>
801 /// <param name="friendList"></param>
802 /// <param name="iAmOnline"></param>
803 private void SendPresenceState(IClientAPI client, List<FriendListItem> friendList, bool iAmOnline)
804 {
805 //m_log.DebugFormat("[FRIEND]: {0} logged {1}; sending presence updates", client.Name, iAmOnline ? "in" : "out");
806
807 if (friendList == null || friendList.Count == 0)
808 {
809 //m_log.DebugFormat("[FRIEND]: {0} doesn't have friends.", client.Name);
810 return; // nothing we can do if she doesn't have friends...
811 }
812
813 // collect sets of friendIDs; to send to (online and offline), and to receive from
814 // TODO: If we ever switch to .NET >= 3, replace those Lists with HashSets.
815 // I can't believe that we have Dictionaries, but no Sets, considering Java introduced them years ago...
816 List<UUID> friendIDsToSendTo = new List<UUID>();
817 List<UUID> candidateFriendIDsToReceive = new List<UUID>();
818
819 foreach (FriendListItem item in friendList)
820 {
821 if (((item.FriendListOwnerPerms | item.FriendPerms) & (uint)FriendRights.CanSeeOnline) != 0)
822 {
823 // friend is allowed to see my presence => add
824 if ((item.FriendListOwnerPerms & (uint)FriendRights.CanSeeOnline) != 0)
825 friendIDsToSendTo.Add(item.Friend);
826
827 if ((item.FriendPerms & (uint)FriendRights.CanSeeOnline) != 0)
828 candidateFriendIDsToReceive.Add(item.Friend);
829 }
830 }
831
832 // we now have a list of "interesting" friends (which we have to find out on-/offline state for),
833 // friends we want to send our online state to (if *they* are online, too), and
834 // friends we want to receive online state for (currently unknown whether online or not)
835
836 // as this processing might take some time and friends might TP away, we try up to three times to
837 // reach them. Most of the time, we *will* reach them, and this loop won't loop
838 int retry = 0;
839 do
840 {
841 // build a list of friends to look up region-information and on-/offline-state for
842 List<UUID> friendIDsToLookup = new List<UUID>(friendIDsToSendTo);
843 foreach (UUID uuid in candidateFriendIDsToReceive)
844 {
845 if (!friendIDsToLookup.Contains(uuid)) friendIDsToLookup.Add(uuid);
846 }
847
848 m_log.DebugFormat(
849 "[FRIEND]: {0} to lookup, {1} to send to, {2} candidates to receive from for agent {3}",
850 friendIDsToLookup.Count, friendIDsToSendTo.Count, candidateFriendIDsToReceive.Count, client.Name);
851
852 // we have to fetch FriendRegionInfos, as the (cached) FriendListItems don't
853 // necessarily contain the correct online state...
854 Dictionary<UUID, FriendRegionInfo> friendRegions = m_initialScene.GetFriendRegionInfos(friendIDsToLookup);
855 m_log.DebugFormat(
856 "[FRIEND]: Found {0} regionInfos for {1} friends of {2}",
857 friendRegions.Count, friendIDsToLookup.Count, client.Name);
858
859 // argument for SendAgentOn/Offline; we shouldn't generate that repeatedly within loops.
860 UUID[] agentArr = new UUID[] { client.AgentId };
861
862 // first, send to friend presence state to me, if I'm online...
863 if (iAmOnline)
864 {
865 List<UUID> friendIDsToReceive = new List<UUID>();
866
867 for (int i = candidateFriendIDsToReceive.Count - 1; i >= 0; --i)
868 {
869 UUID uuid = candidateFriendIDsToReceive[i];
870 FriendRegionInfo info;
871 if (friendRegions.TryGetValue(uuid, out info) && info != null && info.isOnline)
872 {
873 friendIDsToReceive.Add(uuid);
874 }
875 }
876
877 m_log.DebugFormat(
878 "[FRIEND]: Sending {0} online friends to {1}", friendIDsToReceive.Count, client.Name);
879
880 if (friendIDsToReceive.Count > 0)
881 client.SendAgentOnline(friendIDsToReceive.ToArray());
882
883 // clear them for a possible second iteration; we don't have to repeat this
884 candidateFriendIDsToReceive.Clear();
885 }
886
887 // now, send my presence state to my friends
888 for (int i = friendIDsToSendTo.Count - 1; i >= 0; --i)
889 {
890 UUID uuid = friendIDsToSendTo[i];
891 FriendRegionInfo info;
892 if (friendRegions.TryGetValue(uuid, out info) && info != null && info.isOnline)
893 {
894 // any client is good enough, root or child...
895 ScenePresence agent = GetAnyPresenceFromAgentID(uuid);
896 if (agent != null)
897 {
898 m_log.DebugFormat("[FRIEND]: Found local agent {0}", agent.Name);
899
900 // friend is online and on this server...
901 if (iAmOnline) agent.ControllingClient.SendAgentOnline(agentArr);
902 else agent.ControllingClient.SendAgentOffline(agentArr);
903
904 // done, remove it
905 friendIDsToSendTo.RemoveAt(i);
906 }
907 }
908 else
909 {
910 m_log.DebugFormat("[FRIEND]: Friend {0} ({1}) is offline; not sending.", uuid, i);
911
912 // friend is offline => no need to try sending
913 friendIDsToSendTo.RemoveAt(i);
914 }
915 }
916
917 m_log.DebugFormat("[FRIEND]: Have {0} friends to contact via inter-region comms.", friendIDsToSendTo.Count);
918
919 // we now have all the friends left that are online (we think), but not on this region-server
920 if (friendIDsToSendTo.Count > 0)
921 {
922 // sort them into regions
923 Dictionary<ulong, List<UUID>> friendsInRegion = new Dictionary<ulong,List<UUID>>();
924 foreach (UUID uuid in friendIDsToSendTo)
925 {
926 ulong handle = friendRegions[uuid].regionHandle; // this can't fail as we filtered above already
927 List<UUID> friends;
928 if (!friendsInRegion.TryGetValue(handle, out friends))
929 {
930 friends = new List<UUID>();
931 friendsInRegion[handle] = friends;
932 }
933 friends.Add(uuid);
934 }
935 m_log.DebugFormat("[FRIEND]: Found {0} regions to send to.", friendRegions.Count);
936
937 // clear uuids list and collect missed friends in it for the next retry
938 friendIDsToSendTo.Clear();
939
940 // send bulk updates to the region
941 foreach (KeyValuePair<ulong, List<UUID>> pair in friendsInRegion)
942 {
943 m_log.DebugFormat("[FRIEND]: Inform {0} friends in region {1} that user {2} is {3}line",
944 pair.Value.Count, pair.Key, client.Name, iAmOnline ? "on" : "off");
945
946 friendIDsToSendTo.AddRange(m_initialScene.InformFriendsInOtherRegion(client.AgentId, pair.Key, pair.Value, iAmOnline));
947 }
948 }
949 // now we have in friendIDsToSendTo only the agents left that TPed away while we tried to contact them.
950 // In most cases, it will be empty, and it won't loop here. But sometimes, we have to work harder and try again...
951 }
952 while (++retry < 3 && friendIDsToSendTo.Count > 0);
953 }
954
955 private void OnEconomyDataRequest(UUID agentID)
956 {
957 // KLUDGE: This is the only way I found to get a message (only) after login was completed and the
958 // client is connected enough to receive UDP packets).
959 // This packet seems to be sent only once, just after connection was established to the first
960 // region after login.
961 // We use it here to trigger a presence update; the old update-on-login was never be heard by
962 // the freshly logged in viewer, as it wasn't connected to the region at that time.
963 // TODO: Feel free to replace this by a better solution if you find one.
964
965 // get the agent. This should work every time, as we just got a packet from it
966 //ScenePresence agent = GetRootPresenceFromAgentID(agentID);
967 // KLUDGE 2: As this is sent quite early, the avatar isn't here as root agent yet. So, we have to cheat a bit
968 ScenePresence agent = GetAnyPresenceFromAgentID(agentID);
969
970 // just to be paranoid...
971 if (agent == null)
972 {
973 m_log.ErrorFormat("[FRIEND]: Got a packet from agent {0} who can't be found anymore!?", agentID);
974 return;
975 }
976
977 List<FriendListItem> fl;
978 lock (m_friendLists)
979 {
980 fl = (List<FriendListItem>)m_friendLists.Get(agent.ControllingClient.AgentId,
981 m_initialScene.GetFriendList);
982 }
983
984 // tell everyone that we are online
985 SendPresenceState(agent.ControllingClient, fl, true);
986 }
987
988 private void OnLogout(IClientAPI remoteClient)
989 {
990 List<FriendListItem> fl;
991 lock (m_friendLists)
992 {
993 fl = (List<FriendListItem>)m_friendLists.Get(remoteClient.AgentId,
994 m_initialScene.GetFriendList);
995 }
996
997 // tell everyone that we are offline
998 SendPresenceState(remoteClient, fl, false);
999 }
1000 }
1001
1002 #endregion
1003}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Gestures/GesturesModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Gestures/GesturesModule.cs
deleted file mode 100644
index 969c1d8..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Gestures/GesturesModule.cs
+++ /dev/null
@@ -1,104 +0,0 @@
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 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 */
27
28using log4net;
29using Nini.Config;
30using OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Framework.Communications;
33using OpenSim.Framework.Communications.Cache;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36using System.Reflection;
37
38namespace OpenSim.Region.Environment.Modules.Avatar.Gestures
39{
40 public class GesturesModule : IRegionModule
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 protected Scene m_scene;
45
46 public void Initialise(Scene scene, IConfigSource source)
47 {
48 m_scene = scene;
49
50 m_scene.EventManager.OnNewClient += OnNewClient;
51 }
52
53 public void PostInitialise() {}
54 public void Close() {}
55 public string Name { get { return "Gestures Module"; } }
56 public bool IsSharedModule { get { return false; } }
57
58 private void OnNewClient(IClientAPI client)
59 {
60 client.OnActivateGesture += ActivateGesture;
61 client.OnDeactivateGesture += DeactivateGesture;
62 }
63
64 public virtual void ActivateGesture(IClientAPI client, UUID assetId, UUID gestureId)
65 {
66 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(client.AgentId);
67
68 if (userInfo != null)
69 {
70 InventoryItemBase item = userInfo.RootFolder.FindItem(gestureId);
71 if (item != null)
72 {
73 item.Flags = 1;
74 userInfo.UpdateItem(item);
75 }
76 else
77 m_log.ErrorFormat(
78 "[GESTURES]: Unable to find gesture to activate {0} for {1}", gestureId, client.Name);
79 }
80 else
81 m_log.ErrorFormat("[GESTURES]: Unable to find user {0}", client.Name);
82 }
83
84 public virtual void DeactivateGesture(IClientAPI client, UUID gestureId)
85 {
86 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(client.AgentId);
87
88 if (userInfo != null)
89 {
90 InventoryItemBase item = userInfo.RootFolder.FindItem(gestureId);
91 if (item != null)
92 {
93 item.Flags = 0;
94 userInfo.UpdateItem(item);
95 }
96 else
97 m_log.ErrorFormat(
98 "[GESTURES]: Unable to find gesture to deactivate {0} for {1}", gestureId, client.Name);
99 }
100 else
101 m_log.ErrorFormat("[GESTURES]: Unable to find user {0}", client.Name);
102 }
103 }
104} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs
deleted file mode 100644
index e654912..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs
+++ /dev/null
@@ -1,223 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenMetaverse;
32using log4net;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38namespace OpenSim.Region.Environment.Modules.Avatar.Groups
39{
40 public class GroupsModule : IRegionModule
41 {
42 private static readonly ILog m_log =
43 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 private Dictionary<UUID, GroupMembershipData> m_GroupMap =
46 new Dictionary<UUID, GroupMembershipData>();
47
48 private Dictionary<UUID, IClientAPI> m_ClientMap =
49 new Dictionary<UUID, IClientAPI>();
50
51 private UUID opensimulatorGroupID =
52 new UUID("00000000-68f9-1111-024e-222222111123");
53
54 private List<Scene> m_SceneList = new List<Scene>();
55
56 private static GroupMembershipData osGroup =
57 new GroupMembershipData();
58
59 #region IRegionModule Members
60
61 public void Initialise(Scene scene, IConfigSource config)
62 {
63 IConfig groupsConfig = config.Configs["Groups"];
64
65 if (groupsConfig == null)
66 {
67 m_log.Info("[GROUPS]: No configuration found. Using defaults");
68 }
69 else
70 {
71 if (!groupsConfig.GetBoolean("Enabled", false))
72 {
73 m_log.Info("[GROUPS]: Groups disabled in configuration");
74 return;
75 }
76
77 if (groupsConfig.GetString("Module", "Default") != "Default")
78 return;
79 }
80
81 lock (m_SceneList)
82 {
83 if (!m_SceneList.Contains(scene))
84 {
85 if (m_SceneList.Count == 0)
86 {
87 osGroup.GroupID = opensimulatorGroupID;
88 osGroup.GroupName = "OpenSimulator Testing";
89 osGroup.GroupPowers =
90 (uint)(GroupPowers.AllowLandmark |
91 GroupPowers.AllowSetHome);
92 m_GroupMap[opensimulatorGroupID] = osGroup;
93 }
94 m_SceneList.Add(scene);
95 }
96 }
97
98 scene.EventManager.OnNewClient += OnNewClient;
99 scene.EventManager.OnClientClosed += OnClientClosed;
100 scene.EventManager.OnIncomingInstantMessage +=
101 OnGridInstantMessage;
102 }
103
104 public void PostInitialise()
105 {
106 }
107
108 public void Close()
109 {
110// m_log.Debug("[GROUPS]: Shutting down group module.");
111
112 lock (m_ClientMap)
113 {
114 m_ClientMap.Clear();
115 }
116
117 lock (m_GroupMap)
118 {
119 m_GroupMap.Clear();
120 }
121 }
122
123 public string Name
124 {
125 get { return "GroupsModule"; }
126 }
127
128 public bool IsSharedModule
129 {
130 get { return true; }
131 }
132
133 #endregion
134
135 private void OnNewClient(IClientAPI client)
136 {
137 // Subscribe to instant messages
138 client.OnInstantMessage += OnInstantMessage;
139 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
140 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
141 lock (m_ClientMap)
142 {
143 if (!m_ClientMap.ContainsKey(client.AgentId))
144 {
145 m_ClientMap.Add(client.AgentId, client);
146 }
147 }
148
149 GroupMembershipData[] updateGroups = new GroupMembershipData[1];
150 updateGroups[0] = osGroup;
151
152 client.SendGroupMembership(updateGroups);
153 }
154
155 private void OnAgentDataUpdateRequest(IClientAPI remoteClient,
156 UUID AgentID, UUID SessionID)
157 {
158 UUID ActiveGroupID;
159 string ActiveGroupName;
160 ulong ActiveGroupPowers;
161
162 string firstname = remoteClient.FirstName;
163 string lastname = remoteClient.LastName;
164
165 string ActiveGroupTitle = "I IZ N0T";
166
167 ActiveGroupID = osGroup.GroupID;
168 ActiveGroupName = osGroup.GroupName;
169 ActiveGroupPowers = osGroup.GroupPowers;
170
171 remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname,
172 lastname, ActiveGroupPowers, ActiveGroupName,
173 ActiveGroupTitle);
174 }
175
176 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
177 {
178 }
179
180 private void OnGridInstantMessage(GridInstantMessage msg)
181 {
182 // Trigger the above event handler
183 OnInstantMessage(null, msg);
184 }
185
186 private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client)
187 {
188 string groupnamereply = "Unknown";
189 UUID groupUUID = UUID.Zero;
190
191 lock (m_GroupMap)
192 {
193 if (m_GroupMap.ContainsKey(id))
194 {
195 GroupMembershipData grp = m_GroupMap[id];
196 groupnamereply = grp.GroupName;
197 groupUUID = grp.GroupID;
198 }
199 }
200 remote_client.SendGroupNameReply(groupUUID, groupnamereply);
201 }
202
203 private void OnClientClosed(UUID agentID)
204 {
205 lock (m_ClientMap)
206 {
207 if (m_ClientMap.ContainsKey(agentID))
208 {
209// IClientAPI cli = m_ClientMap[agentID];
210// if (cli != null)
211// {
212// //m_log.Info("[GROUPS]: Removing all reference to groups for " + cli.Name);
213// }
214// else
215// {
216// //m_log.Info("[GROUPS]: Removing all reference to groups for " + agentID.ToString());
217// }
218 m_ClientMap.Remove(agentID);
219 }
220 }
221 }
222 }
223}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs
deleted file mode 100644
index 3a1b282..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs
+++ /dev/null
@@ -1,170 +0,0 @@
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 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 System;
28using System.Collections;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Net;
32using System.Threading;
33using OpenMetaverse;
34using log4net;
35using Nini.Config;
36using Nwc.XmlRpc;
37using OpenSim.Framework;
38using OpenSim.Framework.Client;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
43{
44 public class InstantMessageModule : IRegionModule
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 /// <value>
49 /// Is this module enabled?
50 /// </value>
51 private bool m_enabled = false;
52
53 private readonly List<Scene> m_scenes = new List<Scene>();
54
55 #region IRegionModule Members
56
57 private IMessageTransferModule m_TransferModule = null;
58
59 public void Initialise(Scene scene, IConfigSource config)
60 {
61 if (config.Configs["Messaging"] != null)
62 {
63 if (config.Configs["Messaging"].GetString(
64 "InstantMessageModule", "InstantMessageModule") !=
65 "InstantMessageModule")
66 return;
67 }
68
69 m_enabled = true;
70
71 lock (m_scenes)
72 {
73 if (!m_scenes.Contains(scene))
74 {
75 m_scenes.Add(scene);
76 scene.EventManager.OnClientConnect += OnClientConnect;
77 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
78 }
79 }
80 }
81
82 void OnClientConnect(IClientCore client)
83 {
84 IClientIM clientIM;
85 if (client.TryGet(out clientIM))
86 {
87 clientIM.OnInstantMessage += OnInstantMessage;
88 }
89 }
90
91 public void PostInitialise()
92 {
93 if (!m_enabled)
94 return;
95
96 m_TransferModule =
97 m_scenes[0].RequestModuleInterface<IMessageTransferModule>();
98
99 if (m_TransferModule == null)
100 m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+
101 "IM will not work!");
102 }
103
104 public void Close()
105 {
106 }
107
108 public string Name
109 {
110 get { return "InstantMessageModule"; }
111 }
112
113 public bool IsSharedModule
114 {
115 get { return true; }
116 }
117
118 #endregion
119
120 public void OnInstantMessage(IClientAPI client, GridInstantMessage im)
121 {
122 byte dialog = im.dialog;
123
124 if ( dialog != (byte)InstantMessageDialog.MessageFromAgent
125 && dialog != (byte)InstantMessageDialog.StartTyping
126 && dialog != (byte)InstantMessageDialog.StopTyping)
127 {
128 return;
129 }
130
131 if (m_TransferModule != null)
132 {
133 m_TransferModule.SendInstantMessage(im,
134 delegate(bool success)
135 {
136 if (dialog == (uint)InstantMessageDialog.StartTyping ||
137 dialog == (uint)InstantMessageDialog.StopTyping)
138 {
139 return;
140 }
141
142 if ((client != null) && !success)
143 {
144 client.SendInstantMessage(new UUID(im.toAgentID),
145 "Unable to send instant message. "+
146 "User is not logged in.",
147 new UUID(im.fromAgentID), "System",
148 (byte)InstantMessageDialog.BusyAutoResponse,
149 (uint)Util.UnixTimeSinceEpoch());
150 }
151 }
152 );
153 }
154 }
155
156 /// <summary>
157 ///
158 /// </summary>
159 /// <param name="msg"></param>
160 private void OnGridInstantMessage(GridInstantMessage msg)
161 {
162 // Just call the Text IM handler above
163 // This event won't be raised unless we have that agent,
164 // so we can depend on the above not trying to send
165 // via grid again
166 //
167 OnInstantMessage(null, msg);
168 }
169 }
170}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs
deleted file mode 100644
index 347c305..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs
+++ /dev/null
@@ -1,655 +0,0 @@
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 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 System;
28using System.Collections;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Net;
32using System.Threading;
33using OpenMetaverse;
34using log4net;
35using Nini.Config;
36using Nwc.XmlRpc;
37using OpenSim.Framework;
38using OpenSim.Framework.Client;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
43{
44 public class MessageTransferModule : IRegionModule, IMessageTransferModule
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 // private bool m_Enabled = false;
49 private bool m_Gridmode = false;
50 private List<Scene> m_Scenes = new List<Scene>();
51 private Dictionary<UUID, ulong> m_UserRegionMap = new Dictionary<UUID, ulong>();
52
53 public void Initialise(Scene scene, IConfigSource config)
54 {
55 IConfig cnf = config.Configs["Messaging"];
56 if (cnf != null && cnf.GetString(
57 "MessageTransferModule", "MessageTransferModule") !=
58 "MessageTransferModule")
59 return;
60
61 cnf = config.Configs["Startup"];
62 if (cnf != null)
63 m_Gridmode = cnf.GetBoolean("gridmode", false);
64
65 // m_Enabled = true;
66
67 lock (m_Scenes)
68 {
69 if (m_Scenes.Count == 0)
70 {
71 scene.CommsManager.HttpServer.AddXmlRPCHandler(
72 "grid_instant_message", processXMLRPCGridInstantMessage);
73 }
74
75 scene.RegisterModuleInterface<IMessageTransferModule>(this);
76 m_Scenes.Add(scene);
77 }
78 }
79
80 public void PostInitialise()
81 {
82 }
83
84 public void Close()
85 {
86 }
87
88 public string Name
89 {
90 get { return "MessageTransferModule"; }
91 }
92
93 public bool IsSharedModule
94 {
95 get { return true; }
96 }
97
98 public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result)
99 {
100 UUID toAgentID = new UUID(im.toAgentID);
101
102 m_log.DebugFormat("[INSTANT MESSAGE]: Attempting delivery of IM from {0} to {1}", im.fromAgentName, toAgentID.ToString());
103
104 // Try root avatar only first
105 foreach (Scene scene in m_Scenes)
106 {
107 if (scene.Entities.ContainsKey(toAgentID) &&
108 scene.Entities[toAgentID] is ScenePresence)
109 {
110 m_log.DebugFormat("[INSTANT MESSAGE]: Looking for {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName);
111 // Local message
112 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
113 if (!user.IsChildAgent)
114 {
115 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client");
116 user.ControllingClient.SendInstantMessage(
117 new UUID(im.fromAgentID),
118 im.message,
119 new UUID(im.toAgentID),
120 im.fromAgentName,
121 im.dialog,
122 im.timestamp,
123 new UUID(im.imSessionID),
124 im.fromGroup,
125 im.binaryBucket);
126 // Message sent
127 result(true);
128 return;
129 }
130 }
131 }
132
133 // try child avatar second
134 foreach (Scene scene in m_Scenes)
135 {
136// m_log.DebugFormat(
137// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
138
139 if (scene.Entities.ContainsKey(toAgentID) &&
140 scene.Entities[toAgentID] is ScenePresence)
141 {
142 // Local message
143 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
144
145 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client");
146 user.ControllingClient.SendInstantMessage(
147 new UUID(im.fromAgentID),
148 im.message,
149 new UUID(im.toAgentID),
150 im.fromAgentName,
151 im.dialog,
152 im.timestamp,
153 new UUID(im.imSessionID),
154 im.fromGroup,
155 im.binaryBucket);
156 // Message sent
157 result(true);
158 return;
159 }
160 }
161
162 if (m_Gridmode)
163 {
164 //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering via grid");
165 // Still here, try send via Grid
166 SendGridInstantMessageViaXMLRPC(im, result);
167 return;
168 }
169
170 //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable");
171 result(false);
172 return;
173 }
174
175 /// <summary>
176 /// Process a XMLRPC Grid Instant Message
177 /// </summary>
178 /// <param name="request">XMLRPC parameters
179 /// </param>
180 /// <returns>Nothing much</returns>
181 protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request)
182 {
183 bool successful = false;
184
185 // TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that
186 // happen here and aren't caught and log them.
187 try
188 {
189 // various rational defaults
190 UUID fromAgentID = UUID.Zero;
191 UUID toAgentID = UUID.Zero;
192 UUID imSessionID = UUID.Zero;
193 uint timestamp = 0;
194 string fromAgentName = "";
195 string message = "";
196 byte dialog = (byte)0;
197 bool fromGroup = false;
198 byte offline = (byte)0;
199 uint ParentEstateID=0;
200 Vector3 Position = Vector3.Zero;
201 UUID RegionID = UUID.Zero ;
202 byte[] binaryBucket = new byte[0];
203
204 float pos_x = 0;
205 float pos_y = 0;
206 float pos_z = 0;
207 //m_log.Info("Processing IM");
208
209
210 Hashtable requestData = (Hashtable)request.Params[0];
211 // Check if it's got all the data
212 if (requestData.ContainsKey("from_agent_id")
213 && requestData.ContainsKey("to_agent_id") && requestData.ContainsKey("im_session_id")
214 && requestData.ContainsKey("timestamp") && requestData.ContainsKey("from_agent_name")
215 && requestData.ContainsKey("message") && requestData.ContainsKey("dialog")
216 && requestData.ContainsKey("from_group")
217 && requestData.ContainsKey("offline") && requestData.ContainsKey("parent_estate_id")
218 && requestData.ContainsKey("position_x") && requestData.ContainsKey("position_y")
219 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
220 && requestData.ContainsKey("binary_bucket"))
221 {
222 // Do the easy way of validating the UUIDs
223 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
224 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
225 UUID.TryParse((string)requestData["im_session_id"], out imSessionID);
226 UUID.TryParse((string)requestData["region_id"], out RegionID);
227
228 try
229 {
230 timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]);
231 }
232 catch (ArgumentException)
233 {
234 }
235 catch (FormatException)
236 {
237 }
238 catch (OverflowException)
239 {
240 }
241
242 fromAgentName = (string)requestData["from_agent_name"];
243 message = (string)requestData["message"];
244
245 // Bytes don't transfer well over XMLRPC, so, we Base64 Encode them.
246 string requestData1 = (string)requestData["dialog"];
247 if (string.IsNullOrEmpty(requestData1))
248 {
249 dialog = 0;
250 }
251 else
252 {
253 byte[] dialogdata = Convert.FromBase64String(requestData1);
254 dialog = dialogdata[0];
255 }
256
257 if ((string)requestData["from_group"] == "TRUE")
258 fromGroup = true;
259
260 string requestData2 = (string)requestData["offline"];
261 if (String.IsNullOrEmpty(requestData2))
262 {
263 offline = 0;
264 }
265 else
266 {
267 byte[] offlinedata = Convert.FromBase64String(requestData2);
268 offline = offlinedata[0];
269 }
270
271 try
272 {
273 ParentEstateID = (uint)Convert.ToInt32((string)requestData["parent_estate_id"]);
274 }
275 catch (ArgumentException)
276 {
277 }
278 catch (FormatException)
279 {
280 }
281 catch (OverflowException)
282 {
283 }
284
285 try
286 {
287 pos_x = (uint)Convert.ToInt32((string)requestData["position_x"]);
288 }
289 catch (ArgumentException)
290 {
291 }
292 catch (FormatException)
293 {
294 }
295 catch (OverflowException)
296 {
297 }
298 try
299 {
300 pos_y = (uint)Convert.ToInt32((string)requestData["position_y"]);
301 }
302 catch (ArgumentException)
303 {
304 }
305 catch (FormatException)
306 {
307 }
308 catch (OverflowException)
309 {
310 }
311 try
312 {
313 pos_z = (uint)Convert.ToInt32((string)requestData["position_z"]);
314 }
315 catch (ArgumentException)
316 {
317 }
318 catch (FormatException)
319 {
320 }
321 catch (OverflowException)
322 {
323 }
324
325 Position = new Vector3(pos_x, pos_y, pos_z);
326
327 string requestData3 = (string)requestData["binary_bucket"];
328 if (string.IsNullOrEmpty(requestData3))
329 {
330 binaryBucket = new byte[0];
331 }
332 else
333 {
334 binaryBucket = Convert.FromBase64String(requestData3);
335 }
336
337 // Create a New GridInstantMessageObject the the data
338 GridInstantMessage gim = new GridInstantMessage();
339 gim.fromAgentID = fromAgentID.Guid;
340 gim.fromAgentName = fromAgentName;
341 gim.fromGroup = fromGroup;
342 gim.imSessionID = imSessionID.Guid;
343 gim.RegionID = RegionID.Guid;
344 gim.timestamp = timestamp;
345 gim.toAgentID = toAgentID.Guid;
346 gim.message = message;
347 gim.dialog = dialog;
348 gim.offline = offline;
349 gim.ParentEstateID = ParentEstateID;
350 gim.Position = Position;
351 gim.binaryBucket = binaryBucket;
352
353
354 // Trigger the Instant message in the scene.
355 foreach (Scene scene in m_Scenes)
356 {
357 if (scene.Entities.ContainsKey(toAgentID) &&
358 scene.Entities[toAgentID] is ScenePresence)
359 {
360 ScenePresence user =
361 (ScenePresence)scene.Entities[toAgentID];
362
363 if (!user.IsChildAgent)
364 {
365 scene.EventManager.TriggerIncomingInstantMessage(gim);
366 successful = true;
367 }
368 }
369 }
370 if (!successful)
371 {
372 // If the message can't be delivered to an agent, it
373 // is likely to be a group IM. On a group IM, the
374 // imSessionID = toAgentID = group id. Raise the
375 // unhandled IM event to give the groups module
376 // a chance to pick it up. We raise that in a random
377 // scene, since the groups module is shared.
378 //
379 m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim);
380 }
381 }
382 }
383 catch (Exception e)
384 {
385 m_log.Error("[INSTANT MESSAGE]: Caught unexpected exception:", e);
386 successful = false;
387 }
388
389 //Send response back to region calling if it was successful
390 // calling region uses this to know when to look up a user's location again.
391 XmlRpcResponse resp = new XmlRpcResponse();
392 Hashtable respdata = new Hashtable();
393 if (successful)
394 respdata["success"] = "TRUE";
395 else
396 respdata["success"] = "FALSE";
397 resp.Value = respdata;
398
399 return resp;
400 }
401
402 /// <summary>
403 /// delegate for sending a grid instant message asynchronously
404 /// </summary>
405 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, ulong prevRegionHandle);
406
407 private void GridInstantMessageCompleted(IAsyncResult iar)
408 {
409 GridInstantMessageDelegate icon =
410 (GridInstantMessageDelegate)iar.AsyncState;
411 icon.EndInvoke(iar);
412 }
413
414
415 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
416 {
417 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync;
418
419 d.BeginInvoke(im, result, 0, GridInstantMessageCompleted, d);
420 }
421
422 /// <summary>
423 /// Recursive SendGridInstantMessage over XMLRPC method.
424 /// This is called from within a dedicated thread.
425 /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from
426 /// itself, prevRegionHandle will be the last region handle that we tried to send.
427 /// If the handles are the same, we look up the user's location using the grid.
428 /// If the handles are still the same, we end. The send failed.
429 /// </summary>
430 /// <param name="prevRegionHandle">
431 /// Pass in 0 the first time this method is called. It will be called recursively with the last
432 /// regionhandle tried
433 /// </param>
434 protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, ulong prevRegionHandle)
435 {
436 UUID toAgentID = new UUID(im.toAgentID);
437
438 UserAgentData upd = null;
439
440 bool lookupAgent = false;
441
442 lock (m_UserRegionMap)
443 {
444 if (m_UserRegionMap.ContainsKey(toAgentID))
445 {
446 upd = new UserAgentData();
447 upd.AgentOnline = true;
448 upd.Handle = m_UserRegionMap[toAgentID];
449
450 // We need to compare the current regionhandle with the previous region handle
451 // or the recursive loop will never end because it will never try to lookup the agent again
452 if (prevRegionHandle == upd.Handle)
453 {
454 lookupAgent = true;
455 }
456 }
457 else
458 {
459 lookupAgent = true;
460 }
461 }
462
463
464 // Are we needing to look-up an agent?
465 if (lookupAgent)
466 {
467 // Non-cached user agent lookup.
468 upd = m_Scenes[0].CommsManager.UserService.GetAgentByUUID(toAgentID);
469
470 if (upd != null)
471 {
472 // check if we've tried this before..
473 // This is one way to end the recursive loop
474 //
475 if (upd.Handle == prevRegionHandle)
476 {
477 m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
478 result(false);
479 return;
480 }
481 }
482 else
483 {
484 m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
485 result(false);
486 return;
487 }
488 }
489
490 if (upd != null)
491 {
492 if (upd.AgentOnline)
493 {
494 RegionInfo reginfo = m_Scenes[0].SceneGridService.RequestNeighbouringRegionInfo(upd.Handle);
495 if (reginfo != null)
496 {
497 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
498 // Not actually used anymore, left in for compatibility
499 // Remove at next interface change
500 //
501 msgdata["region_handle"] = 0;
502 bool imresult = doIMSending(reginfo, msgdata);
503 if (imresult)
504 {
505 // IM delivery successful, so store the Agent's location in our local cache.
506 lock (m_UserRegionMap)
507 {
508 if (m_UserRegionMap.ContainsKey(toAgentID))
509 {
510 m_UserRegionMap[toAgentID] = upd.Handle;
511 }
512 else
513 {
514 m_UserRegionMap.Add(toAgentID, upd.Handle);
515 }
516 }
517 result(true);
518 }
519 else
520 {
521 // try again, but lookup user this time.
522 // Warning, this must call the Async version
523 // of this method or we'll be making thousands of threads
524 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
525 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
526
527 // This is recursive!!!!!
528 SendGridInstantMessageViaXMLRPCAsync(im, result,
529 upd.Handle);
530 }
531
532 }
533 else
534 {
535 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.Handle);
536 result(false);
537 }
538 }
539 else
540 {
541 result(false);
542 }
543 }
544 else
545 {
546 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find user {0}", toAgentID);
547 result(false);
548 }
549
550 }
551
552 /// <summary>
553 /// This actually does the XMLRPC Request
554 /// </summary>
555 /// <param name="reginfo">RegionInfo we pull the data out of to send the request to</param>
556 /// <param name="xmlrpcdata">The Instant Message data Hashtable</param>
557 /// <returns>Bool if the message was successfully delivered at the other side.</returns>
558 private bool doIMSending(RegionInfo reginfo, Hashtable xmlrpcdata)
559 {
560
561 ArrayList SendParams = new ArrayList();
562 SendParams.Add(xmlrpcdata);
563 XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams);
564 try
565 {
566
567 XmlRpcResponse GridResp = GridReq.Send("http://" + reginfo.ExternalHostName + ":" + reginfo.HttpPort, 3000);
568
569 Hashtable responseData = (Hashtable)GridResp.Value;
570
571 if (responseData.ContainsKey("success"))
572 {
573 if ((string)responseData["success"] == "TRUE")
574 {
575 return true;
576 }
577 else
578 {
579 return false;
580 }
581 }
582 else
583 {
584 return false;
585 }
586 }
587 catch (WebException e)
588 {
589 m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to http://{0}:{1} the host didn't respond ({2})",
590 reginfo.ExternalHostName, reginfo.HttpPort, e.Message);
591 }
592
593 return false;
594 }
595
596 /// <summary>
597 /// Get ulong region handle for region by it's Region UUID.
598 /// We use region handles over grid comms because there's all sorts of free and cool caching.
599 /// </summary>
600 /// <param name="regionID">UUID of region to get the region handle for</param>
601 /// <returns></returns>
602// private ulong getLocalRegionHandleFromUUID(UUID regionID)
603// {
604// ulong returnhandle = 0;
605//
606// lock (m_Scenes)
607// {
608// foreach (Scene sn in m_Scenes)
609// {
610// if (sn.RegionInfo.RegionID == regionID)
611// {
612// returnhandle = sn.RegionInfo.RegionHandle;
613// break;
614// }
615// }
616// }
617// return returnhandle;
618// }
619
620 /// <summary>
621 /// Takes a GridInstantMessage and converts it into a Hashtable for XMLRPC
622 /// </summary>
623 /// <param name="msg">The GridInstantMessage object</param>
624 /// <returns>Hashtable containing the XMLRPC request</returns>
625 private Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg)
626 {
627 Hashtable gim = new Hashtable();
628 gim["from_agent_id"] = msg.fromAgentID.ToString();
629 // Kept for compatibility
630 gim["from_agent_session"] = UUID.Zero.ToString();
631 gim["to_agent_id"] = msg.toAgentID.ToString();
632 gim["im_session_id"] = msg.imSessionID.ToString();
633 gim["timestamp"] = msg.timestamp.ToString();
634 gim["from_agent_name"] = msg.fromAgentName;
635 gim["message"] = msg.message;
636 byte[] dialogdata = new byte[1];dialogdata[0] = msg.dialog;
637 gim["dialog"] = Convert.ToBase64String(dialogdata,Base64FormattingOptions.None);
638
639 if (msg.fromGroup)
640 gim["from_group"] = "TRUE";
641 else
642 gim["from_group"] = "FALSE";
643 byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline;
644 gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None);
645 gim["parent_estate_id"] = msg.ParentEstateID.ToString();
646 gim["position_x"] = msg.Position.X.ToString();
647 gim["position_y"] = msg.Position.Y.ToString();
648 gim["position_z"] = msg.Position.Z.ToString();
649 gim["region_id"] = msg.RegionID.ToString();
650 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
651 return gim;
652 }
653
654 }
655}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs
deleted file mode 100644
index c84d3d5..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs
+++ /dev/null
@@ -1,426 +0,0 @@
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 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 System;
28using System.Collections;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Net;
32using System.Threading;
33using OpenMetaverse;
34using log4net;
35using Nini.Config;
36using Nwc.XmlRpc;
37using OpenSim.Framework;
38using OpenSim.Framework.Client;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
43{
44 public class PresenceModule : IRegionModule, IPresenceModule
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 private bool m_Enabled = false;
49 private bool m_Gridmode = false;
50
51 // some default scene for doing things that aren't connected to a specific scene. Avoids locking.
52 private Scene m_initialScene;
53
54 private List<Scene> m_Scenes = new List<Scene>();
55
56 // we currently are only interested in root-agents. If the root isn't here, we don't know the region the
57 // user is in, so we have to ask the messaging server anyway.
58 private Dictionary<UUID, Scene> m_RootAgents =
59 new Dictionary<UUID, Scene>();
60
61 public event PresenceChange OnPresenceChange;
62 public event BulkPresenceData OnBulkPresenceData;
63
64 public void Initialise(Scene scene, IConfigSource config)
65 {
66 lock (m_Scenes)
67 {
68 // This is a shared module; Initialise will be called for every region on this server.
69 // Only check config once for the first region.
70 if (m_Scenes.Count == 0)
71 {
72 IConfig cnf = config.Configs["Messaging"];
73 if (cnf != null && cnf.GetString(
74 "PresenceModule", "PresenceModule") !=
75 "PresenceModule")
76 return;
77
78 cnf = config.Configs["Startup"];
79 if (cnf != null)
80 m_Gridmode = cnf.GetBoolean("gridmode", false);
81
82 m_Enabled = true;
83
84 m_initialScene = scene;
85 }
86
87 if (m_Gridmode)
88 NotifyMessageServerOfStartup(scene);
89
90 m_Scenes.Add(scene);
91 }
92
93 scene.RegisterModuleInterface<IPresenceModule>(this);
94
95 scene.EventManager.OnNewClient += OnNewClient;
96 scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
97 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
98 }
99
100 public void PostInitialise()
101 {
102 }
103
104 public void Close()
105 {
106 if (!m_Gridmode || !m_Enabled)
107 return;
108
109 if (OnPresenceChange != null)
110 {
111 lock (m_RootAgents)
112 {
113 // on shutdown, users are kicked, too
114 foreach (KeyValuePair<UUID, Scene> pair in m_RootAgents)
115 {
116 OnPresenceChange(new PresenceInfo(pair.Key, UUID.Zero));
117 }
118 }
119 }
120
121 lock (m_Scenes)
122 {
123 foreach (Scene scene in m_Scenes)
124 NotifyMessageServerOfShutdown(scene);
125 }
126 }
127
128 public string Name
129 {
130 get { return "PresenceModule"; }
131 }
132
133 public bool IsSharedModule
134 {
135 get { return true; }
136 }
137
138 public void RequestBulkPresenceData(UUID[] users)
139 {
140 if (OnBulkPresenceData != null)
141 {
142 PresenceInfo[] result = new PresenceInfo[users.Length];
143 if (m_Gridmode)
144 {
145 // first check the local information
146 List<UUID> uuids = new List<UUID>(); // the uuids to check remotely
147 List<int> indices = new List<int>(); // just for performance.
148 lock (m_RootAgents)
149 {
150 for (int i = 0; i < uuids.Count; ++i)
151 {
152 Scene scene;
153 if (m_RootAgents.TryGetValue(users[i], out scene))
154 {
155 result[i] = new PresenceInfo(users[i], scene.RegionInfo.RegionID);
156 }
157 else
158 {
159 uuids.Add(users[i]);
160 indices.Add(i);
161 }
162 }
163 }
164
165 // now we have filtered out all the local root agents. The rest we have to request info about
166 Dictionary<UUID, FriendRegionInfo> infos = m_initialScene.GetFriendRegionInfos(uuids);
167 for (int i = 0; i < uuids.Count; ++i)
168 {
169 FriendRegionInfo info;
170 if (infos.TryGetValue(uuids[i], out info) && info.isOnline)
171 {
172 UUID regionID = info.regionID;
173 if (regionID == UUID.Zero)
174 {
175 // TODO this is the old messaging-server protocol; only the regionHandle is available.
176 // Fetch region-info to get the id
177 RegionInfo regionInfo = m_initialScene.RequestNeighbouringRegionInfo(info.regionHandle);
178 regionID = regionInfo.RegionID;
179 }
180 result[indices[i]] = new PresenceInfo(uuids[i], regionID);
181 }
182 else result[indices[i]] = new PresenceInfo(uuids[i], UUID.Zero);
183 }
184 }
185 else
186 {
187 // in standalone mode, we have all the info locally available.
188 lock (m_RootAgents)
189 {
190 for (int i = 0; i < users.Length; ++i)
191 {
192 Scene scene;
193 if (m_RootAgents.TryGetValue(users[i], out scene))
194 {
195 result[i] = new PresenceInfo(users[i], scene.RegionInfo.RegionID);
196 }
197 else
198 {
199 result[i] = new PresenceInfo(users[i], UUID.Zero);
200 }
201 }
202 }
203 }
204
205 // tell everyone
206 OnBulkPresenceData(result);
207 }
208 }
209
210 // new client doesn't mean necessarily that user logged in, it just means it entered one of the
211 // the regions on this server
212 public void OnNewClient(IClientAPI client)
213 {
214 client.OnConnectionClosed += OnConnectionClosed;
215 client.OnLogout += OnLogout;
216
217 // KLUDGE: See handler for details.
218 client.OnEconomyDataRequest += OnEconomyDataRequest;
219 }
220
221 // connection closed just means *one* client connection has been closed. It doesn't mean that the
222 // user has logged off; it might have just TPed away.
223 public void OnConnectionClosed(IClientAPI client)
224 {
225 // TODO: Have to think what we have to do here...
226 // Should we just remove the root from the list (if scene matches)?
227 if (!(client.Scene is Scene))
228 return;
229 Scene scene = (Scene)client.Scene;
230
231 lock (m_RootAgents)
232 {
233 Scene rootScene;
234 if (!(m_RootAgents.TryGetValue(client.AgentId, out rootScene)) || scene != rootScene)
235 return;
236
237 m_RootAgents.Remove(client.AgentId);
238 }
239
240 // Should it have logged off, we'll do the logout part in OnLogout, even if no root is stored
241 // anymore. It logged off, after all...
242 }
243
244 // Triggered when the user logs off.
245 public void OnLogout(IClientAPI client)
246 {
247 if (!(client.Scene is Scene))
248 return;
249 Scene scene = (Scene)client.Scene;
250
251 // On logout, we really remove the client from rootAgents, even if the scene doesn't match
252 lock (m_RootAgents)
253 {
254 if (m_RootAgents.ContainsKey(client.AgentId)) m_RootAgents.Remove(client.AgentId);
255 }
256
257 // now inform the messaging server and anyone who is interested
258 NotifyMessageServerOfAgentLeaving(client.AgentId, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle);
259 if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(client.AgentId, UUID.Zero));
260 }
261
262 public void OnSetRootAgentScene(UUID agentID, Scene scene)
263 {
264 // OnSetRootAgentScene can be called from several threads at once (with different agentID).
265 // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without
266 // correct locking).
267 lock (m_RootAgents)
268 {
269 Scene rootScene;
270 if (m_RootAgents.TryGetValue(agentID, out rootScene) && scene == rootScene)
271 {
272 return;
273 }
274 m_RootAgents[agentID] = scene;
275 }
276 // inform messaging server that agent changed the region
277 NotifyMessageServerOfAgentLocation(agentID, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle);
278 }
279
280 private void OnEconomyDataRequest(UUID agentID)
281 {
282 // KLUDGE: This is the only way I found to get a message (only) after login was completed and the
283 // client is connected enough to receive UDP packets.
284 // This packet seems to be sent only once, just after connection was established to the first
285 // region after login.
286 // We use it here to trigger a presence update; the old update-on-login was never be heard by
287 // the freshly logged in viewer, as it wasn't connected to the region at that time.
288 // TODO: Feel free to replace this by a better solution if you find one.
289
290 // get the agent. This should work every time, as we just got a packet from it
291 ScenePresence agent = null;
292 lock (m_Scenes)
293 {
294 foreach (Scene scene in m_Scenes)
295 {
296 agent = scene.GetScenePresence(agentID);
297 if (agent != null) break;
298 }
299 }
300
301 // just to be paranoid...
302 if (agent == null)
303 {
304 m_log.ErrorFormat("[PRESENCE]: Got a packet from agent {0} who can't be found anymore!?", agentID);
305 return;
306 }
307
308 // we are a bit premature here, but the next packet will switch this child agent to root.
309 if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(agentID, agent.Scene.RegionInfo.RegionID));
310 }
311
312 public void OnMakeChildAgent(ScenePresence agent)
313 {
314 // OnMakeChildAgent can be called from several threads at once (with different agent).
315 // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without
316 // correct locking).
317 lock (m_RootAgents)
318 {
319 Scene rootScene;
320 if (m_RootAgents.TryGetValue(agent.UUID, out rootScene) && agent.Scene == rootScene)
321 {
322 m_RootAgents.Remove(agent.UUID);
323 }
324 }
325 // don't notify the messaging-server; either this agent just had been downgraded and another one will be upgraded
326 // to root momentarily (which will notify the messaging-server), or possibly it will be closed in a moment,
327 // which will update the messaging-server, too.
328 }
329
330 private void NotifyMessageServerOfStartup(Scene scene)
331 {
332 Hashtable xmlrpcdata = new Hashtable();
333 xmlrpcdata["RegionUUID"] = scene.RegionInfo.RegionID.ToString();
334 ArrayList SendParams = new ArrayList();
335 SendParams.Add(xmlrpcdata);
336 try
337 {
338 XmlRpcRequest UpRequest = new XmlRpcRequest("region_startup", SendParams);
339 XmlRpcResponse resp = UpRequest.Send(scene.CommsManager.NetworkServersInfo.MessagingURL, 5000);
340
341 Hashtable responseData = (Hashtable)resp.Value;
342 if (responseData == null || (!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE")
343 {
344 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region startup for region {0}", scene.RegionInfo.RegionName);
345 }
346 }
347 catch (System.Net.WebException)
348 {
349 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region startup for region {0}", scene.RegionInfo.RegionName);
350 }
351 }
352
353 private void NotifyMessageServerOfShutdown(Scene scene)
354 {
355 Hashtable xmlrpcdata = new Hashtable();
356 xmlrpcdata["RegionUUID"] = scene.RegionInfo.RegionID.ToString();
357 ArrayList SendParams = new ArrayList();
358 SendParams.Add(xmlrpcdata);
359 try
360 {
361 XmlRpcRequest DownRequest = new XmlRpcRequest("region_shutdown", SendParams);
362 XmlRpcResponse resp = DownRequest.Send(scene.CommsManager.NetworkServersInfo.MessagingURL, 5000);
363
364 Hashtable responseData = (Hashtable)resp.Value;
365 if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE")
366 {
367 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region shutdown for region {0}", scene.RegionInfo.RegionName);
368 }
369 }
370 catch (System.Net.WebException)
371 {
372 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region shutdown for region {0}", scene.RegionInfo.RegionName);
373 }
374 }
375
376 private void NotifyMessageServerOfAgentLocation(UUID agentID, UUID region, ulong regionHandle)
377 {
378 Hashtable xmlrpcdata = new Hashtable();
379 xmlrpcdata["AgentID"] = agentID.ToString();
380 xmlrpcdata["RegionUUID"] = region.ToString();
381 xmlrpcdata["RegionHandle"] = regionHandle.ToString();
382 ArrayList SendParams = new ArrayList();
383 SendParams.Add(xmlrpcdata);
384 try
385 {
386 XmlRpcRequest LocationRequest = new XmlRpcRequest("agent_location", SendParams);
387 XmlRpcResponse resp = LocationRequest.Send(m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL, 5000);
388
389 Hashtable responseData = (Hashtable)resp.Value;
390 if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE")
391 {
392 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent location for {0}", agentID.ToString());
393 }
394 }
395 catch (System.Net.WebException)
396 {
397 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent location for {0}", agentID.ToString());
398 }
399 }
400
401 private void NotifyMessageServerOfAgentLeaving(UUID agentID, UUID region, ulong regionHandle)
402 {
403 Hashtable xmlrpcdata = new Hashtable();
404 xmlrpcdata["AgentID"] = agentID.ToString();
405 xmlrpcdata["RegionUUID"] = region.ToString();
406 xmlrpcdata["RegionHandle"] = regionHandle.ToString();
407 ArrayList SendParams = new ArrayList();
408 SendParams.Add(xmlrpcdata);
409 try
410 {
411 XmlRpcRequest LeavingRequest = new XmlRpcRequest("agent_leaving", SendParams);
412 XmlRpcResponse resp = LeavingRequest.Send(m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL, 5000);
413
414 Hashtable responseData = (Hashtable)resp.Value;
415 if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE")
416 {
417 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent leaving for {0}", agentID.ToString());
418 }
419 }
420 catch (System.Net.WebException)
421 {
422 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent leaving for {0}", agentID.ToString());
423 }
424 }
425 }
426}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
deleted file mode 100644
index 3a58202..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ /dev/null
@@ -1,279 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.IO.Compression;
32using System.Reflection;
33using System.Xml;
34using OpenMetaverse;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Environment.Modules.World.Archiver;
37using OpenSim.Framework;
38using OpenSim.Framework.Communications;
39using OpenSim.Framework.Communications.Cache;
40using log4net;
41using OpenSim.Region.Environment.Modules.World.Serialiser;
42
43
44namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Archiver
45{
46 public class InventoryArchiveReadRequest
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 protected Scene scene;
51 protected TarArchiveReader archive;
52 private static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding();
53
54 CommunicationsManager commsManager;
55
56 public InventoryArchiveReadRequest(Scene currentScene, CommunicationsManager commsManager)
57 {
58 //List<string> serialisedObjects = new List<string>();
59 scene = currentScene;
60 this.commsManager = commsManager;
61 }
62
63 protected InventoryItemBase loadInvItem(string path, string contents)
64 {
65 InventoryItemBase item = new InventoryItemBase();
66 StringReader sr = new StringReader(contents);
67 XmlTextReader reader = new XmlTextReader(sr);
68
69 if (contents.Equals("")) return null;
70
71 reader.ReadStartElement("InventoryObject");
72 reader.ReadStartElement("Name");
73 item.Name = reader.ReadString();
74 reader.ReadEndElement();
75 reader.ReadStartElement("ID");
76 item.ID = UUID.Parse(reader.ReadString());
77 reader.ReadEndElement();
78 reader.ReadStartElement("InvType");
79 item.InvType = System.Convert.ToInt32(reader.ReadString());
80 reader.ReadEndElement();
81 reader.ReadStartElement("CreatorUUID");
82 item.Creator = UUID.Parse(reader.ReadString());
83 reader.ReadEndElement();
84 reader.ReadStartElement("CreationDate");
85 item.CreationDate = System.Convert.ToInt32(reader.ReadString());
86 reader.ReadEndElement();
87 reader.ReadStartElement("Owner");
88 item.Owner = UUID.Parse(reader.ReadString());
89 reader.ReadEndElement();
90 //No description would kill it
91 if (reader.IsEmptyElement)
92 {
93 reader.ReadStartElement("Description");
94 }
95 else
96 {
97 reader.ReadStartElement("Description");
98 item.Description = reader.ReadString();
99 reader.ReadEndElement();
100 }
101 reader.ReadStartElement("AssetType");
102 item.AssetType = System.Convert.ToInt32(reader.ReadString());
103 reader.ReadEndElement();
104 reader.ReadStartElement("AssetID");
105 item.AssetID = UUID.Parse(reader.ReadString());
106 reader.ReadEndElement();
107 reader.ReadStartElement("SaleType");
108 item.SaleType = System.Convert.ToByte(reader.ReadString());
109 reader.ReadEndElement();
110 reader.ReadStartElement("SalePrice");
111 item.SalePrice = System.Convert.ToInt32(reader.ReadString());
112 reader.ReadEndElement();
113 reader.ReadStartElement("BasePermissions");
114 item.BasePermissions = System.Convert.ToUInt32(reader.ReadString());
115 reader.ReadEndElement();
116 reader.ReadStartElement("CurrentPermissions");
117 item.CurrentPermissions = System.Convert.ToUInt32(reader.ReadString());
118 reader.ReadEndElement();
119 reader.ReadStartElement("EveryOnePermssions");
120 item.EveryOnePermissions = System.Convert.ToUInt32(reader.ReadString());
121 reader.ReadEndElement();
122 reader.ReadStartElement("NextPermissions");
123 item.NextPermissions = System.Convert.ToUInt32(reader.ReadString());
124 reader.ReadEndElement();
125 reader.ReadStartElement("Flags");
126 item.Flags = System.Convert.ToUInt32(reader.ReadString());
127 reader.ReadEndElement();
128 reader.ReadStartElement("GroupID");
129 item.GroupID = UUID.Parse(reader.ReadString());
130 reader.ReadEndElement();
131 reader.ReadStartElement("GroupOwned");
132 item.GroupOwned = System.Convert.ToBoolean(reader.ReadString());
133 reader.ReadEndElement();
134 //reader.ReadStartElement("ParentFolderID");
135 //item.Folder = UUID.Parse(reader.ReadString());
136 //reader.ReadEndElement();
137 //reader.ReadEndElement();
138
139 return item;
140 }
141
142 public void execute(string firstName, string lastName, string invPath, string loadPath)
143 {
144 string filePath = "ERROR";
145 int successfulAssetRestores = 0;
146 int failedAssetRestores = 0;
147 int successfulItemRestores = 0;
148
149 UserProfileData userProfile = commsManager.UserService.GetUserProfile(firstName, lastName);
150 if (null == userProfile)
151 {
152 m_log.ErrorFormat("[CONSOLE]: Failed to find user {0} {1}", firstName, lastName);
153 return;
154 }
155
156 CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userProfile.ID);
157 if (null == userInfo)
158 {
159 m_log.ErrorFormat(
160 "[CONSOLE]: Failed to find user info for {0} {1} {2}",
161 firstName, lastName, userProfile.ID);
162
163 return;
164 }
165
166 if (!userInfo.HasReceivedInventory)
167 {
168 m_log.ErrorFormat(
169 "[CONSOLE]: Have not yet received inventory info for user {0} {1} {2}",
170 firstName, lastName, userProfile.ID);
171
172 return;
173 }
174
175 InventoryFolderImpl inventoryFolder = userInfo.RootFolder.FindFolderByPath(invPath);
176
177 if (null == inventoryFolder)
178 {
179 // TODO: Later on, automatically create this folder if it does not exist
180 m_log.ErrorFormat("[ARCHIVER]: Inventory path {0} does not exist", invPath);
181
182 return;
183 }
184
185 archive
186 = new TarArchiveReader(new GZipStream(
187 new FileStream(loadPath, FileMode.Open), CompressionMode.Decompress));
188
189 byte[] data;
190 TarArchiveReader.TarEntryType entryType;
191 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
192 {
193 if (entryType == TarArchiveReader.TarEntryType.TYPE_DIRECTORY) {
194 m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}", filePath);
195 } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
196 {
197 if (LoadAsset(filePath, data))
198 successfulAssetRestores++;
199 else
200 failedAssetRestores++;
201 }
202 else
203 {
204 InventoryItemBase item = loadInvItem(filePath, m_asciiEncoding.GetString(data));
205
206 if (item != null)
207 {
208 item.Creator = userProfile.ID;
209 item.Owner = userProfile.ID;
210
211 // Reset folder ID to the one in which we want to load it
212 // TODO: Properly restore entire folder structure. At the moment all items are dumped in this
213 // single folder no matter where in the saved folder structure they are.
214 item.Folder = inventoryFolder.ID;
215
216 userInfo.AddItem(item);
217 successfulItemRestores++;
218 }
219 }
220 }
221
222 archive.Close();
223
224 m_log.DebugFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores);
225 m_log.InfoFormat("[ARCHIVER]: Restored {0} items", successfulItemRestores);
226 }
227
228 /// <summary>
229 /// Load an asset
230 /// </summary>
231 /// <param name="assetFilename"></param>
232 /// <param name="data"></param>
233 /// <returns>true if asset was successfully loaded, false otherwise</returns>
234 private bool LoadAsset(string assetPath, byte[] data)
235 {
236 //IRegionSerialiser serialiser = scene.RequestModuleInterface<IRegionSerialiser>();
237 // Right now we're nastily obtaining the UUID from the filename
238 string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
239 int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
240
241 if (i == -1)
242 {
243 m_log.ErrorFormat(
244 "[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping",
245 assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
246
247 return false;
248 }
249
250 string extension = filename.Substring(i);
251 string uuid = filename.Remove(filename.Length - extension.Length);
252
253 if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
254 {
255 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
256
257 m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
258
259 AssetBase asset = new AssetBase(new UUID(uuid), "RandomName");
260
261 asset.Metadata.Type = assetType;
262 asset.Data = data;
263
264 scene.AssetCache.AddAsset(asset);
265
266
267 return true;
268 }
269 else
270 {
271 m_log.ErrorFormat(
272 "[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
273 assetPath, extension);
274
275 return false;
276 }
277 }
278 }
279}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
deleted file mode 100644
index e23f2a8..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ /dev/null
@@ -1,247 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.IO.Compression;
32using System.Reflection;
33using System.Xml;
34using OpenMetaverse;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Environment.Modules.World.Archiver;
37using OpenSim.Framework;
38using OpenSim.Framework.Communications;
39using OpenSim.Framework.Communications.Cache;
40using log4net;
41
42
43namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Archiver
44{
45 public class InventoryArchiveWriteRequest
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 protected Scene scene;
50 protected TarArchiveWriter archive;
51 protected CommunicationsManager commsManager;
52 Dictionary<UUID, int> assetUuids;
53
54 /// <value>
55 /// The path to which the inventory archive will be saved.
56 /// </value>
57 private string m_savePath;
58
59 public InventoryArchiveWriteRequest(Scene currentScene, CommunicationsManager commsManager)
60 {
61 scene = currentScene;
62 archive = new TarArchiveWriter();
63 this.commsManager = commsManager;
64 assetUuids = new Dictionary<UUID, int>();
65 }
66
67 protected void ReceivedAllAssets(IDictionary<UUID, AssetBase> assetsFound, ICollection<UUID> assetsNotFoundUuids)
68 {
69 AssetsArchiver assetsArchiver = new AssetsArchiver(assetsFound);
70 assetsArchiver.Archive(archive);
71 archive.WriteTar(new GZipStream(new FileStream(m_savePath, FileMode.Create), CompressionMode.Compress));
72 }
73
74 protected void saveInvItem(InventoryItemBase inventoryItem, string path)
75 {
76 string filename
77 = string.Format("{0}{1}_{2}.xml",
78 path, inventoryItem.Name, inventoryItem.ID);
79 StringWriter sw = new StringWriter();
80 XmlTextWriter writer = new XmlTextWriter(sw);
81 writer.WriteStartElement("InventoryObject");
82 writer.WriteStartElement("Name");
83 writer.WriteString(inventoryItem.Name);
84 writer.WriteEndElement();
85 writer.WriteStartElement("ID");
86 writer.WriteString(inventoryItem.ID.ToString());
87 writer.WriteEndElement();
88 writer.WriteStartElement("InvType");
89 writer.WriteString(inventoryItem.InvType.ToString());
90 writer.WriteEndElement();
91 writer.WriteStartElement("CreatorUUID");
92 writer.WriteString(inventoryItem.Creator.ToString());
93 writer.WriteEndElement();
94 writer.WriteStartElement("CreationDate");
95 writer.WriteString(inventoryItem.CreationDate.ToString());
96 writer.WriteEndElement();
97 writer.WriteStartElement("Owner");
98 writer.WriteString(inventoryItem.Owner.ToString());
99 writer.WriteEndElement();
100 writer.WriteStartElement("Description");
101 if (inventoryItem.Description.Length > 0)
102 writer.WriteString(inventoryItem.Description);
103 else writer.WriteString("No Description");
104 writer.WriteEndElement();
105 writer.WriteStartElement("AssetType");
106 writer.WriteString(inventoryItem.AssetType.ToString());
107 writer.WriteEndElement();
108 writer.WriteStartElement("AssetID");
109 writer.WriteString(inventoryItem.AssetID.ToString());
110 writer.WriteEndElement();
111 writer.WriteStartElement("SaleType");
112 writer.WriteString(inventoryItem.SaleType.ToString());
113 writer.WriteEndElement();
114 writer.WriteStartElement("SalePrice");
115 writer.WriteString(inventoryItem.SalePrice.ToString());
116 writer.WriteEndElement();
117 writer.WriteStartElement("BasePermissions");
118 writer.WriteString(inventoryItem.BasePermissions.ToString());
119 writer.WriteEndElement();
120 writer.WriteStartElement("CurrentPermissions");
121 writer.WriteString(inventoryItem.CurrentPermissions.ToString());
122 writer.WriteEndElement();
123 writer.WriteStartElement("EveryOnePermssions");
124 writer.WriteString(inventoryItem.EveryOnePermissions.ToString());
125 writer.WriteEndElement();
126 writer.WriteStartElement("NextPermissions");
127 writer.WriteString(inventoryItem.NextPermissions.ToString());
128 writer.WriteEndElement();
129 writer.WriteStartElement("Flags");
130 writer.WriteString(inventoryItem.Flags.ToString());
131 writer.WriteEndElement();
132 writer.WriteStartElement("GroupID");
133 writer.WriteString(inventoryItem.GroupID.ToString());
134 writer.WriteEndElement();
135 writer.WriteStartElement("GroupOwned");
136 writer.WriteString(inventoryItem.GroupOwned.ToString());
137 writer.WriteEndElement();
138 writer.WriteStartElement("ParentFolderID");
139 writer.WriteString(inventoryItem.Folder.ToString());
140 writer.WriteEndElement();
141 writer.WriteEndElement();
142
143 archive.AddFile(filename, sw.ToString());
144
145 assetUuids[inventoryItem.AssetID] = 1;
146 }
147
148 protected void saveInvDir(InventoryFolderImpl inventoryFolder, string path)
149 {
150 List<InventoryFolderImpl> inventories = inventoryFolder.RequestListOfFolderImpls();
151 List<InventoryItemBase> items = inventoryFolder.RequestListOfItems();
152 string newPath = path + inventoryFolder.Name + InventoryFolderImpl.PATH_DELIMITER;
153 archive.AddDir(newPath);
154 foreach (InventoryFolderImpl folder in inventories)
155 {
156 saveInvDir(folder, newPath);
157 }
158 foreach (InventoryItemBase item in items)
159 {
160 saveInvItem(item, newPath);
161 }
162 }
163
164 public void execute(string firstName, string lastName, string invPath, string savePath)
165 {
166 m_savePath = savePath;
167
168 UserProfileData userProfile = commsManager.UserService.GetUserProfile(firstName, lastName);
169 if (null == userProfile)
170 {
171 m_log.ErrorFormat("[CONSOLE]: Failed to find user {0} {1}", firstName, lastName);
172 return;
173 }
174
175 CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userProfile.ID);
176 if (null == userInfo)
177 {
178 m_log.ErrorFormat("[CONSOLE]: Failed to find user info for {0} {1} {2}", firstName, lastName, userProfile.ID);
179 return;
180 }
181
182 InventoryFolderImpl inventoryFolder = null;
183 InventoryItemBase inventoryItem = null;
184
185 if (userInfo.HasReceivedInventory)
186 {
187 // Eliminate double slashes and any leading / on the path. This might be better done within InventoryFolderImpl
188 // itself (possibly at a small loss in efficiency).
189 string[] components
190 = invPath.Split(new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries);
191 invPath = String.Empty;
192 foreach (string c in components)
193 {
194 invPath += c + InventoryFolderImpl.PATH_DELIMITER;
195 }
196
197 // Annoyingly Split actually returns the original string if the input string consists only of delimiters
198 // Therefore if we still start with a / after the split, then we need the root folder
199 if (invPath.Length == 0)
200 {
201 inventoryFolder = userInfo.RootFolder;
202 }
203 else
204 {
205 invPath = invPath.Remove(invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
206 inventoryFolder = userInfo.RootFolder.FindFolderByPath(invPath);
207 }
208
209 // The path may point to an item instead
210 if (inventoryFolder == null)
211 {
212 inventoryItem = userInfo.RootFolder.FindItemByPath(invPath);
213 }
214 }
215 else
216 {
217 m_log.ErrorFormat("[CONSOLE]: Have not yet received inventory info for user {0} {1} {2}", firstName, lastName, userProfile.ID);
218 return;
219 }
220
221 if (null == inventoryFolder)
222 {
223 if (null == inventoryItem)
224 {
225 m_log.ErrorFormat("[CONSOLE]: Could not find inventory entry at path {0}", invPath);
226 return;
227 }
228 else
229 {
230 m_log.InfoFormat("[CONSOLE]: Found item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID,
231 invPath);
232 //get and export item info
233 saveInvItem(inventoryItem, invPath);
234 }
235 }
236 else
237 {
238 m_log.InfoFormat("[CONSOLE]: Found folder {0} {1} at {2}", inventoryFolder.Name, inventoryFolder.ID,
239 invPath);
240 //recurse through all dirs getting dirs and files
241 saveInvDir(inventoryFolder, "");
242 }
243
244 new AssetsRequest(assetUuids.Keys, scene.AssetCache, ReceivedAllAssets).Execute();
245 }
246 }
247}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
deleted file mode 100644
index 62fb3a2..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ /dev/null
@@ -1,389 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenMetaverse;
33using log4net;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Framework.Communications.Cache;
39
40namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
41{
42 public class InventoryTransferModule : IInventoryTransferModule, IRegionModule
43 {
44 private static readonly ILog m_log
45 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 /// <summary>
48 private List<Scene> m_Scenelist = new List<Scene>();
49 private Dictionary<UUID, Scene> m_AgentRegions =
50 new Dictionary<UUID, Scene>();
51
52 private IMessageTransferModule m_TransferModule = null;
53
54 #region IRegionModule Members
55
56 public void Initialise(Scene scene, IConfigSource config)
57 {
58 if (config.Configs["Messaging"] != null)
59 {
60 // Allow disabling this module in config
61 //
62 if (config.Configs["Messaging"].GetString(
63 "InventoryTransferModule", "InventoryTransferModule") !=
64 "InventoryTransferModule")
65 return;
66 }
67
68 if (!m_Scenelist.Contains(scene))
69 {
70 if (m_Scenelist.Count == 0)
71 {
72 m_TransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
73 if (m_TransferModule == null)
74 m_log.Error("[INVENTORY TRANSFER] No Message transfer module found, transfers will be local only");
75 }
76
77 m_Scenelist.Add(scene);
78
79 scene.RegisterModuleInterface<IInventoryTransferModule>(this);
80
81 scene.EventManager.OnNewClient += OnNewClient;
82 scene.EventManager.OnClientClosed += ClientLoggedOut;
83 }
84 }
85
86 public void PostInitialise()
87 {
88 }
89
90 public void Close()
91 {
92 }
93
94 public string Name
95 {
96 get { return "InventoryModule"; }
97 }
98
99 public bool IsSharedModule
100 {
101 get { return true; }
102 }
103
104 #endregion
105
106 private void OnNewClient(IClientAPI client)
107 {
108 // Inventory giving is conducted via instant message
109 client.OnInstantMessage += OnInstantMessage;
110 }
111
112 private Scene FindClientScene(UUID agentId)
113 {
114 lock (m_Scenelist)
115 {
116 foreach (Scene scene in m_Scenelist)
117 {
118 ScenePresence presence = scene.GetScenePresence(agentId);
119 if (presence != null)
120 {
121 if (!presence.IsChildAgent)
122 return scene;
123 }
124 }
125 }
126 return null;
127 }
128
129 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
130 {
131 Scene scene = FindClientScene(client.AgentId);
132
133 if (scene == null) // Something seriously wrong here.
134 return;
135
136 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
137 {
138 //m_log.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0]));
139
140 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
141 UUID copyID;
142
143 // First byte is the asset type
144 AssetType assetType = (AssetType)im.binaryBucket[0];
145
146 if (AssetType.Folder == assetType)
147 {
148 UUID folderID = new UUID(im.binaryBucket, 1);
149
150 m_log.DebugFormat("[AGENT INVENTORY]: Inserting original folder {0} "+
151 "into agent {1}'s inventory",
152 folderID, new UUID(im.toAgentID));
153
154 InventoryFolderImpl folderCopy
155 = scene.GiveInventoryFolder(new UUID(im.toAgentID), client.AgentId, folderID, UUID.Zero);
156
157 if (folderCopy == null)
158 {
159 client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false);
160 return;
161 }
162
163 // The outgoing binary bucket should contain only the byte which signals an asset folder is
164 // being copied and the following bytes for the copied folder's UUID
165 copyID = folderCopy.ID;
166 byte[] copyIDBytes = copyID.GetBytes();
167 im.binaryBucket = new byte[1 + copyIDBytes.Length];
168 im.binaryBucket[0] = (byte)AssetType.Folder;
169 Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length);
170
171 if (user != null && !user.IsChildAgent)
172 {
173 user.ControllingClient.SendBulkUpdateInventory(folderCopy);
174 }
175 }
176 else
177 {
178 // First byte of the array is probably the item type
179 // Next 16 bytes are the UUID
180
181 UUID itemID = new UUID(im.binaryBucket, 1);
182
183 m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+
184 "into agent {1}'s inventory",
185 itemID, new UUID(im.toAgentID));
186
187 InventoryItemBase itemCopy = scene.GiveInventoryItem(
188 new UUID(im.toAgentID),
189 client.AgentId, itemID);
190
191 if (itemCopy == null)
192 {
193 client.SendAgentAlertMessage("Can't find item to give. Nothing given.", false);
194 return;
195 }
196
197 copyID = itemCopy.ID;
198 Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16);
199
200 if (user != null && !user.IsChildAgent)
201 {
202 user.ControllingClient.SendBulkUpdateInventory(itemCopy);
203 }
204 }
205
206 // Send the IM to the recipient. The item is already
207 // in their inventory, so it will not be lost if
208 // they are offline.
209 //
210 if (user != null && !user.IsChildAgent)
211 {
212 // And notify. Transaction ID is the item ID. We get that
213 // same ID back on the reply so we know what to act on
214 //
215 user.ControllingClient.SendInstantMessage(
216 new UUID(im.fromAgentID), im.message,
217 new UUID(im.toAgentID),
218 im.fromAgentName, im.dialog, im.timestamp,
219 copyID, false, im.binaryBucket);
220
221 return;
222 }
223 else
224 {
225 if (m_TransferModule != null)
226 m_TransferModule.SendInstantMessage(im, delegate(bool success) {} );
227 }
228 }
229 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
230 {
231 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
232
233 if (user != null) // Local
234 {
235 user.ControllingClient.SendInstantMessage(
236 new UUID(im.fromAgentID), im.message,
237 new UUID(im.toAgentID),
238 im.fromAgentName, im.dialog, im.timestamp,
239 UUID.Zero, false, im.binaryBucket);
240 }
241 else
242 {
243 if (m_TransferModule != null)
244 m_TransferModule.SendInstantMessage(im, delegate(bool success) {} );
245 }
246 }
247 else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
248 {
249 // Here, the recipient is local and we can assume that the
250 // inventory is loaded. Courtesy of the above bulk update,
251 // It will have been pushed to the client, too
252 //
253
254 CachedUserInfo userInfo =
255 scene.CommsManager.UserProfileCacheService.
256 GetUserDetails(client.AgentId);
257
258 if (userInfo != null)
259 {
260 InventoryFolderImpl trashFolder =
261 userInfo.FindFolderForType((int)AssetType.TrashFolder);
262
263 UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
264
265 InventoryItemBase item = userInfo.RootFolder.FindItem(inventoryEntityID);
266 InventoryFolderBase folder = null;
267
268 if (item != null && trashFolder != null)
269 {
270 item.Folder = trashFolder.ID;
271
272 userInfo.DeleteItem(inventoryEntityID);
273
274 scene.AddInventoryItem(client, item);
275 }
276 else
277 {
278 folder = userInfo.RootFolder.FindFolder(inventoryEntityID);
279
280 if (folder != null & trashFolder != null)
281 {
282 userInfo.MoveFolder(inventoryEntityID, trashFolder.ID);
283 }
284 }
285
286 if ((null == item && null == folder) | null == trashFolder)
287 {
288 string reason = String.Empty;
289
290 if (trashFolder == null)
291 reason += " Trash folder not found.";
292 if (item == null)
293 reason += " Item not found.";
294 if (folder == null)
295 reason += " Folder not found.";
296
297 client.SendAgentAlertMessage("Unable to delete "+
298 "received inventory" + reason, false);
299 }
300 }
301
302 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
303
304 if (user != null) // Local
305 {
306 user.ControllingClient.SendInstantMessage(
307 new UUID(im.fromAgentID), im.message,
308 new UUID(im.toAgentID),
309 im.fromAgentName, im.dialog, im.timestamp,
310 UUID.Zero, false, im.binaryBucket);
311 }
312 else
313 {
314 if (m_TransferModule != null)
315 m_TransferModule.SendInstantMessage(im, delegate(bool success) {} );
316 }
317 }
318 }
319
320 public void SetRootAgentScene(UUID agentID, Scene scene)
321 {
322 m_AgentRegions[agentID] = scene;
323 }
324
325 public bool NeedSceneCacheClear(UUID agentID, Scene scene)
326 {
327 if (!m_AgentRegions.ContainsKey(agentID))
328 {
329 // Since we can get here two ways, we need to scan
330 // the scenes here. This is somewhat more expensive
331 // but helps avoid a nasty bug
332 //
333
334 foreach (Scene s in m_Scenelist)
335 {
336 ScenePresence presence;
337
338 if (s.TryGetAvatar(agentID, out presence))
339 {
340 // If the agent is in this scene, then we
341 // are being called twice in a single
342 // teleport. This is wasteful of cycles
343 // but harmless due to this 2nd level check
344 //
345 // If the agent is found in another scene
346 // then the list wasn't current
347 //
348 // If the agent is totally unknown, then what
349 // are we even doing here??
350 //
351 if (s == scene)
352 {
353 //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
354 return true;
355 }
356 else
357 {
358 //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
359 return false;
360 }
361 }
362 }
363 //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
364 return true;
365 }
366
367 // The agent is left in current Scene, so we must be
368 // going to another instance
369 //
370 if (m_AgentRegions[agentID] == scene)
371 {
372 //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
373 m_AgentRegions.Remove(agentID);
374 return true;
375 }
376
377 // Another region has claimed the agent
378 //
379 //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
380 return false;
381 }
382
383 public void ClientLoggedOut(UUID agentID)
384 {
385 if (m_AgentRegions.ContainsKey(agentID))
386 m_AgentRegions.Remove(agentID);
387 }
388 }
389}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Lure/LureModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Lure/LureModule.cs
deleted file mode 100644
index 79d5409..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Lure/LureModule.cs
+++ /dev/null
@@ -1,176 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Net;
33using System.Threading;
34using OpenMetaverse;
35using log4net;
36using Nini.Config;
37using Nwc.XmlRpc;
38using OpenSim.Framework;
39using OpenSim.Framework.Client;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42
43namespace OpenSim.Region.Environment.Modules.Avatar.Lure
44{
45 public class LureModule : IRegionModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private readonly List<Scene> m_scenes = new List<Scene>();
50
51 private IMessageTransferModule m_TransferModule = null;
52
53 public void Initialise(Scene scene, IConfigSource config)
54 {
55 if (config.Configs["Messaging"] != null)
56 {
57 if (config.Configs["Messaging"].GetString(
58 "LureModule", "LureModule") !=
59 "LureModule")
60 return;
61 }
62
63 lock (m_scenes)
64 {
65 if (!m_scenes.Contains(scene))
66 {
67 m_scenes.Add(scene);
68 scene.EventManager.OnNewClient += OnNewClient;
69 scene.EventManager.OnIncomingInstantMessage +=
70 OnGridInstantMessage;
71 }
72 }
73 }
74
75 void OnNewClient(IClientAPI client)
76 {
77 client.OnInstantMessage += OnInstantMessage;
78 client.OnStartLure += OnStartLure;
79 client.OnTeleportLureRequest += OnTeleportLureRequest;
80 }
81
82 public void PostInitialise()
83 {
84 m_TransferModule =
85 m_scenes[0].RequestModuleInterface<IMessageTransferModule>();
86
87 if (m_TransferModule == null)
88 m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+
89 "lures will not work!");
90 }
91
92 public void Close()
93 {
94 }
95
96 public string Name
97 {
98 get { return "LureModule"; }
99 }
100
101 public bool IsSharedModule
102 {
103 get { return true; }
104 }
105
106 public void OnInstantMessage(IClientAPI client, GridInstantMessage im)
107 {
108 }
109
110 public void OnStartLure(byte lureType, string message, UUID targetid, IClientAPI client)
111 {
112 if (!(client.Scene is Scene))
113 return;
114
115 Scene scene = (Scene)(client.Scene);
116 ScenePresence presence = scene.GetScenePresence(client.AgentId);
117
118 UUID dest = Util.BuildFakeParcelID(
119 scene.RegionInfo.RegionHandle,
120 (uint)presence.AbsolutePosition.X,
121 (uint)presence.AbsolutePosition.Y,
122 (uint)presence.AbsolutePosition.Z);
123
124 m_log.DebugFormat("TP invite with message {0}", message);
125
126 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId,
127 client.FirstName+" "+client.LastName, targetid,
128 (byte)InstantMessageDialog.RequestTeleport, false,
129 message, dest, false, presence.AbsolutePosition,
130 new Byte[0]);
131
132 if (m_TransferModule != null)
133 {
134 m_TransferModule.SendInstantMessage(m,
135 delegate(bool success) { });
136 }
137 }
138
139 public void OnTeleportLureRequest(UUID lureID, uint teleportFlags, IClientAPI client)
140 {
141 if (!(client.Scene is Scene))
142 return;
143
144 Scene scene = (Scene)(client.Scene);
145
146 ulong handle = 0;
147 uint x = 128;
148 uint y = 128;
149 uint z = 70;
150
151 Util.ParseFakeParcelID(lureID, out handle, out x, out y, out z);
152
153 Vector3 position = new Vector3();
154 position.X = (float)x;
155 position.Y = (float)y;
156 position.Z = (float)z;
157
158 scene.RequestTeleportLocation(client, handle, position,
159 Vector3.Zero, teleportFlags);
160 }
161
162 private void OnGridInstantMessage(GridInstantMessage msg)
163 {
164 // Forward remote teleport requests
165 //
166 if (msg.dialog != 22)
167 return;
168
169 if (m_TransferModule != null)
170 {
171 m_TransferModule.SendInstantMessage(msg,
172 delegate(bool success) { });
173 }
174 }
175 }
176}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/Environment/Modules/Avatar/ObjectCaps/ObjectAdd.cs
deleted file mode 100644
index c853582..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/ObjectCaps/ObjectAdd.cs
+++ /dev/null
@@ -1,368 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Reflection;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35using OpenSim.Framework;
36using OpenSim.Framework.Servers;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
40
41namespace OpenSim.Region.Environment.Modules.Avatar.ObjectCaps
42{
43 public class ObjectAdd : IRegionModule
44 {
45 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private Scene m_scene;
48 #region IRegionModule Members
49
50 public void Initialise(Scene pScene, IConfigSource pSource)
51 {
52 m_scene = pScene;
53 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
54 }
55
56 public void PostInitialise()
57 {
58
59 }
60
61 public void RegisterCaps(UUID agentID, Caps caps)
62 {
63 UUID capuuid = UUID.Random();
64
65 m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/");
66
67 caps.RegisterHandler("ObjectAdd",
68 new RestHTTPHandler("POST", "/CAPS/OA/" + capuuid + "/",
69 delegate(Hashtable m_dhttpMethod)
70 {
71 return ProcessAdd(m_dhttpMethod, agentID, caps);
72 }));
73 }
74
75 public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap)
76 {
77 Hashtable responsedata = new Hashtable();
78 responsedata["int_response_code"] = 400; //501; //410; //404;
79 responsedata["content_type"] = "text/plain";
80 responsedata["keepalive"] = false;
81 responsedata["str_response_string"] = "Request wasn't what was expected";
82 ScenePresence avatar;
83
84 if (!m_scene.TryGetAvatar(AgentId, out avatar))
85 return responsedata;
86
87
88 OSD r = OSDParser.DeserializeLLSDXml((string)request["requestbody"]);
89 //UUID session_id = UUID.Zero;
90 bool bypass_raycast = false;
91 uint everyone_mask = 0;
92 uint group_mask = 0;
93 uint next_owner_mask = 0;
94 uint flags = 0;
95 UUID group_id = UUID.Zero;
96 int hollow = 0;
97 int material = 0;
98 int p_code = 0;
99 int path_begin = 0;
100 int path_curve = 0;
101 int path_end = 0;
102 int path_radius_offset = 0;
103 int path_revolutions = 0;
104 int path_scale_x = 0;
105 int path_scale_y = 0;
106 int path_shear_x = 0;
107 int path_shear_y = 0;
108 int path_skew = 0;
109 int path_taper_x = 0;
110 int path_taper_y = 0;
111 int path_twist = 0;
112 int path_twist_begin = 0;
113 int profile_begin = 0;
114 int profile_curve = 0;
115 int profile_end = 0;
116 Vector3 ray_end = Vector3.Zero;
117 bool ray_end_is_intersection = false;
118 Vector3 ray_start = Vector3.Zero;
119 UUID ray_target_id = UUID.Zero;
120 Quaternion rotation = Quaternion.Identity;
121 Vector3 scale = Vector3.Zero;
122 int state = 0;
123
124 if (r.Type != OSDType.Map) // not a proper req
125 return responsedata;
126
127 OSDMap rm = (OSDMap)r;
128
129 if (rm.ContainsKey("ObjectData")) //v2
130 {
131 if (rm["ObjectData"].Type != OSDType.Map)
132 {
133 responsedata["str_response_string"] = "Has ObjectData key, but data not in expected format";
134 return responsedata;
135 }
136
137 OSDMap ObjMap = (OSDMap) rm["ObjectData"];
138
139 bypass_raycast = ObjMap["BypassRaycast"].AsBoolean();
140 everyone_mask = readuintval(ObjMap["EveryoneMask"]);
141 flags = readuintval(ObjMap["Flags"]);
142 group_mask = readuintval(ObjMap["GroupMask"]);
143 material = ObjMap["Material"].AsInteger();
144 next_owner_mask = readuintval(ObjMap["NextOwnerMask"]);
145 p_code = ObjMap["PCode"].AsInteger();
146
147 if (ObjMap.ContainsKey("Path"))
148 {
149 if (ObjMap["Path"].Type != OSDType.Map)
150 {
151 responsedata["str_response_string"] = "Has Path key, but data not in expected format";
152 return responsedata;
153 }
154
155 OSDMap PathMap = (OSDMap)ObjMap["Path"];
156 path_begin = PathMap["Begin"].AsInteger();
157 path_curve = PathMap["Curve"].AsInteger();
158 path_end = PathMap["End"].AsInteger();
159 path_radius_offset = PathMap["RadiusOffset"].AsInteger();
160 path_revolutions = PathMap["Revolutions"].AsInteger();
161 path_scale_x = PathMap["ScaleX"].AsInteger();
162 path_scale_y = PathMap["ScaleY"].AsInteger();
163 path_shear_x = PathMap["ShearX"].AsInteger();
164 path_shear_y = PathMap["ShearY"].AsInteger();
165 path_skew = PathMap["Skew"].AsInteger();
166 path_taper_x = PathMap["TaperX"].AsInteger();
167 path_taper_y = PathMap["TaperY"].AsInteger();
168 path_twist = PathMap["Twist"].AsInteger();
169 path_twist_begin = PathMap["TwistBegin"].AsInteger();
170
171 }
172
173 if (ObjMap.ContainsKey("Profile"))
174 {
175 if (ObjMap["Profile"].Type != OSDType.Map)
176 {
177 responsedata["str_response_string"] = "Has Profile key, but data not in expected format";
178 return responsedata;
179 }
180
181 OSDMap ProfileMap = (OSDMap)ObjMap["Profile"];
182
183 profile_begin = ProfileMap["Begin"].AsInteger();
184 profile_curve = ProfileMap["Curve"].AsInteger();
185 profile_end = ProfileMap["End"].AsInteger();
186 hollow = ProfileMap["Hollow"].AsInteger();
187 }
188 ray_end_is_intersection = ObjMap["RayEndIsIntersection"].AsBoolean();
189
190 ray_target_id = ObjMap["RayTargetId"].AsUUID();
191 state = ObjMap["State"].AsInteger();
192 try
193 {
194 ray_end = ((OSDArray) ObjMap["RayEnd"]).AsVector3();
195 ray_start = ((OSDArray) ObjMap["RayStart"]).AsVector3();
196 scale = ((OSDArray) ObjMap["Scale"]).AsVector3();
197 rotation = ((OSDArray)ObjMap["Rotation"]).AsQuaternion();
198 }
199 catch (Exception)
200 {
201 responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format";
202 return responsedata;
203 }
204
205 if (rm.ContainsKey("AgentData"))
206 {
207 if (rm["AgentData"].Type != OSDType.Map)
208 {
209 responsedata["str_response_string"] = "Has AgentData key, but data not in expected format";
210 return responsedata;
211 }
212
213 OSDMap AgentDataMap = (OSDMap) rm["AgentData"];
214
215 //session_id = AgentDataMap["SessionId"].AsUUID();
216 group_id = AgentDataMap["GroupId"].AsUUID();
217 }
218
219 }
220 else
221 { //v1
222 bypass_raycast = rm["bypass_raycast"].AsBoolean();
223
224 everyone_mask = readuintval(rm["everyone_mask"]);
225 flags = readuintval(rm["flags"]);
226 group_id = rm["group_id"].AsUUID();
227 group_mask = readuintval(rm["group_mask"]);
228 hollow = rm["hollow"].AsInteger();
229 material = rm["material"].AsInteger();
230 next_owner_mask = readuintval(rm["next_owner_mask"]);
231 hollow = rm["hollow"].AsInteger();
232 p_code = rm["p_code"].AsInteger();
233 path_begin = rm["path_begin"].AsInteger();
234 path_curve = rm["path_curve"].AsInteger();
235 path_end = rm["path_end"].AsInteger();
236 path_radius_offset = rm["path_radius_offset"].AsInteger();
237 path_revolutions = rm["path_revolutions"].AsInteger();
238 path_scale_x = rm["path_scale_x"].AsInteger();
239 path_scale_y = rm["path_scale_y"].AsInteger();
240 path_shear_x = rm["path_shear_x"].AsInteger();
241 path_shear_y = rm["path_shear_y"].AsInteger();
242 path_skew = rm["path_skew"].AsInteger();
243 path_taper_x = rm["path_taper_x"].AsInteger();
244 path_taper_y = rm["path_taper_y"].AsInteger();
245 path_twist = rm["path_twist"].AsInteger();
246 path_twist_begin = rm["path_twist_begin"].AsInteger();
247 profile_begin = rm["profile_begin"].AsInteger();
248 profile_curve = rm["profile_curve"].AsInteger();
249 profile_end = rm["profile_end"].AsInteger();
250
251 ray_end_is_intersection = rm["ray_end_is_intersection"].AsBoolean();
252
253 ray_target_id = rm["ray_target_id"].AsUUID();
254
255
256 //session_id = rm["session_id"].AsUUID();
257 state = rm["state"].AsInteger();
258 try
259 {
260 ray_end = ((OSDArray)rm["ray_end"]).AsVector3();
261 ray_start = ((OSDArray)rm["ray_start"]).AsVector3();
262 rotation = ((OSDArray)rm["rotation"]).AsQuaternion();
263 scale = ((OSDArray)rm["scale"]).AsVector3();
264 }
265 catch (Exception)
266 {
267 responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format";
268 return responsedata;
269 }
270 }
271
272
273
274 Vector3 pos = m_scene.GetNewRezLocation(ray_start, ray_end, ray_target_id, rotation, (bypass_raycast) ? (byte)1 : (byte)0, (ray_end_is_intersection) ? (byte)1 : (byte)0, true, scale, false);
275
276 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
277
278 pbs.PathBegin = (ushort)path_begin;
279 pbs.PathCurve = (byte)path_curve;
280 pbs.PathEnd = (ushort)path_end;
281 pbs.PathRadiusOffset = (sbyte)path_radius_offset;
282 pbs.PathRevolutions = (byte)path_revolutions;
283 pbs.PathScaleX = (byte)path_scale_x;
284 pbs.PathScaleY = (byte)path_scale_y;
285 pbs.PathShearX = (byte) path_shear_x;
286 pbs.PathShearY = (byte)path_shear_y;
287 pbs.PathSkew = (sbyte)path_skew;
288 pbs.PathTaperX = (sbyte)path_taper_x;
289 pbs.PathTaperY = (sbyte)path_taper_y;
290 pbs.PathTwist = (sbyte)path_twist;
291 pbs.PathTwistBegin = (sbyte)path_twist_begin;
292 pbs.HollowShape = (HollowShape) hollow;
293 pbs.PCode = (byte)p_code;
294 pbs.ProfileBegin = (ushort) profile_begin;
295 pbs.ProfileCurve = (byte) profile_curve;
296 pbs.ProfileEnd = (ushort)profile_end;
297 pbs.Scale = scale;
298 pbs.State = (byte)state;
299
300 SceneObjectGroup obj = null; ;
301
302 if (m_scene.Permissions.CanRezObject(1, avatar.UUID, pos))
303 {
304 // rez ON the ground, not IN the ground
305 pos.Z += 0.25F;
306
307 obj = m_scene.AddNewPrim(avatar.UUID, group_id, pos, rotation, pbs);
308 }
309
310
311 if (obj == null)
312 return responsedata;
313
314 SceneObjectPart rootpart = obj.RootPart;
315 rootpart.Shape = pbs;
316 rootpart.Flags |= (PrimFlags)flags;
317 rootpart.EveryoneMask = everyone_mask;
318 rootpart.GroupID = group_id;
319 rootpart.GroupMask = group_mask;
320 rootpart.NextOwnerMask = next_owner_mask;
321 rootpart.Material = (byte)material;
322
323
324
325 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
326
327 responsedata["int_response_code"] = 200; //501; //410; //404;
328 responsedata["content_type"] = "text/plain";
329 responsedata["keepalive"] = false;
330 responsedata["str_response_string"] = String.Format("<llsd><map><key>local_id</key>{0}</map></llsd>",ConvertUintToBytes(obj.LocalId));
331
332 return responsedata;
333 }
334
335 private uint readuintval(OSD obj)
336 {
337 byte[] tmp = obj.AsBinary();
338 if (BitConverter.IsLittleEndian)
339 Array.Reverse(tmp);
340 return Utils.BytesToUInt(tmp);
341
342 }
343 private string ConvertUintToBytes(uint val)
344 {
345 byte[] resultbytes = Utils.UIntToBytes(val);
346 if (BitConverter.IsLittleEndian)
347 Array.Reverse(resultbytes);
348 return String.Format("<binary encoding=\"base64\">{0}</binary>",Convert.ToBase64String(resultbytes));
349 }
350
351 public void Close()
352 {
353
354 }
355
356 public string Name
357 {
358 get { return "ObjectAddModule"; }
359 }
360
361 public bool IsSharedModule
362 {
363 get { return false; }
364 }
365
366 #endregion
367 }
368}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs
deleted file mode 100644
index a7e9849..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs
+++ /dev/null
@@ -1,145 +0,0 @@
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 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 */
27
28using System;
29using System.Globalization;
30using System.Reflection;
31using OpenMetaverse;
32using log4net;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38namespace OpenSim.Region.Environment.Modules.Avatar.Profiles
39{
40 public class AvatarProfilesModule : IRegionModule
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private Scene m_scene;
44
45 public AvatarProfilesModule()
46 {
47 }
48
49 #region IRegionModule Members
50
51 public void Initialise(Scene scene, IConfigSource config)
52 {
53 m_scene = scene;
54 m_scene.EventManager.OnNewClient += NewClient;
55 }
56
57 public void PostInitialise()
58 {
59 }
60
61 public void Close()
62 {
63 }
64
65 public string Name
66 {
67 get { return "AvatarProfilesModule"; }
68 }
69
70 public bool IsSharedModule
71 {
72 get { return false; }
73 }
74
75 #endregion
76
77 public void NewClient(IClientAPI client)
78 {
79 client.OnRequestAvatarProperties += RequestAvatarProperty;
80 client.OnUpdateAvatarProperties += UpdateAvatarProperties;
81 }
82
83 public void RemoveClient(IClientAPI client)
84 {
85 client.OnRequestAvatarProperties -= RequestAvatarProperty;
86 client.OnUpdateAvatarProperties -= UpdateAvatarProperties;
87 }
88
89 /// <summary>
90 ///
91 /// </summary>
92 /// <param name="remoteClient"></param>
93 /// <param name="avatarID"></param>
94 public void RequestAvatarProperty(IClientAPI remoteClient, UUID avatarID)
95 {
96 // FIXME: finish adding fields such as url, masking, etc.
97 UserProfileData profile = m_scene.CommsManager.UserService.GetUserProfile(avatarID);
98 if (null != profile)
99 {
100 Byte[] charterMember;
101 if (profile.CustomType == "")
102 {
103 charterMember = new Byte[1];
104 charterMember[0] = (Byte)((profile.UserFlags & 0xf00) >> 8);
105 }
106 else
107 {
108 charterMember = Utils.StringToBytes(profile.CustomType);
109 }
110
111 remoteClient.SendAvatarProperties(profile.ID, profile.AboutText,
112 Util.ToDateTime(profile.Created).ToString("M/d/yyyy", CultureInfo.InvariantCulture),
113 charterMember, profile.FirstLifeAboutText, (uint)(profile.UserFlags & 0xff),
114 profile.FirstLifeImage, profile.Image, String.Empty, profile.Partner);
115 }
116 else
117 {
118 m_log.Debug("[AvatarProfilesModule]: Got null for profile for " + avatarID.ToString());
119 }
120 }
121
122 public void UpdateAvatarProperties(IClientAPI remoteClient, UserProfileData newProfile)
123 {
124 UserProfileData Profile = m_scene.CommsManager.UserService.GetUserProfile(newProfile.ID);
125
126 // if it's the profile of the user requesting the update, then we change only a few things.
127 if (remoteClient.AgentId.CompareTo(Profile.ID) == 0)
128 {
129 Profile.Image = newProfile.Image;
130 Profile.FirstLifeImage = newProfile.FirstLifeImage;
131 Profile.AboutText = newProfile.AboutText;
132 Profile.FirstLifeAboutText = newProfile.FirstLifeAboutText;
133 }
134 else
135 {
136 return;
137 }
138
139 if (m_scene.CommsManager.UserService.UpdateUserProfile(Profile))
140 {
141 RequestAvatarProperty(remoteClient, newProfile.ID);
142 }
143 }
144 }
145}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs
deleted file mode 100644
index 33d7135..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs
+++ /dev/null
@@ -1,292 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Reflection;
31using OpenMetaverse;
32using log4net;
33using Nini.Config;
34using Nwc.XmlRpc;
35using OpenSim.Framework;
36using OpenSim.Framework.Communications.Cache;
37using OpenSim.Framework.Communications.Capabilities;
38using OpenSim.Framework.Servers;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41using Caps=OpenSim.Framework.Communications.Capabilities.Caps;
42
43namespace OpenSim.Region.Environment.Modules.Avatar.Voice.AsterixVoice
44{
45 public class AsteriskVoiceModule : IRegionModule
46 {
47 private static readonly ILog m_log =
48 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 private static readonly string m_parcelVoiceInfoRequestPath = "0007/";
51 private static readonly string m_provisionVoiceAccountRequestPath = "0008/";
52
53 private string m_asterisk;
54 private string m_asterisk_password;
55 private string m_asterisk_salt;
56 private int m_asterisk_timeout;
57 private string m_confDomain;
58 private IConfig m_config;
59 private Scene m_scene;
60 private string m_sipDomain;
61
62 #region IRegionModule Members
63
64 public void Initialise(Scene scene, IConfigSource config)
65 {
66 m_scene = scene;
67 m_config = config.Configs["AsteriskVoice"];
68
69 if (null == m_config)
70 {
71 m_log.Info("[ASTERISKVOICE] no config found, plugin disabled");
72 return;
73 }
74
75 if (!m_config.GetBoolean("enabled", false))
76 {
77 m_log.Info("[ASTERISKVOICE] plugin disabled by configuration");
78 return;
79 }
80 m_log.Info("[ASTERISKVOICE] plugin enabled");
81
82 try
83 {
84 m_sipDomain = m_config.GetString("sip_domain", String.Empty);
85 m_log.InfoFormat("[ASTERISKVOICE] using SIP domain {0}", m_sipDomain);
86
87 m_confDomain = m_config.GetString("conf_domain", String.Empty);
88 m_log.InfoFormat("[ASTERISKVOICE] using conf domain {0}", m_confDomain);
89
90 m_asterisk = m_config.GetString("asterisk_frontend", String.Empty);
91 m_asterisk_password = m_config.GetString("asterisk_password", String.Empty);
92 m_asterisk_timeout = m_config.GetInt("asterisk_timeout", 3000);
93 m_asterisk_salt = m_config.GetString("asterisk_salt", "Wuffwuff");
94 if (String.IsNullOrEmpty(m_asterisk)) throw new Exception("missing asterisk_frontend config parameter");
95 if (String.IsNullOrEmpty(m_asterisk_password)) throw new Exception("missing asterisk_password config parameter");
96 m_log.InfoFormat("[ASTERISKVOICE] using asterisk front end {0}", m_asterisk);
97
98 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
99 }
100 catch (Exception e)
101 {
102 m_log.ErrorFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.Message);
103 m_log.DebugFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.ToString());
104 return;
105 }
106 }
107
108 public void PostInitialise()
109 {
110 }
111
112 public void Close()
113 {
114 }
115
116 public string Name
117 {
118 get { return "AsteriskVoiceModule"; }
119 }
120
121 public bool IsSharedModule
122 {
123 get { return false; }
124 }
125
126 #endregion
127
128 public void OnRegisterCaps(UUID agentID, Caps caps)
129 {
130 m_log.DebugFormat("[ASTERISKVOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
131 string capsBase = "/CAPS/" + caps.CapsObjectPath;
132 caps.RegisterHandler("ParcelVoiceInfoRequest",
133 new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath,
134 delegate(string request, string path, string param,
135 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
136 {
137 return ParcelVoiceInfoRequest(request, path, param,
138 agentID, caps);
139 }));
140 caps.RegisterHandler("ProvisionVoiceAccountRequest",
141 new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath,
142 delegate(string request, string path, string param,
143 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
144 {
145 return ProvisionVoiceAccountRequest(request, path, param,
146 agentID, caps);
147 }));
148 }
149
150 /// <summary>
151 /// Callback for a client request for ParcelVoiceInfo
152 /// </summary>
153 /// <param name="request"></param>
154 /// <param name="path"></param>
155 /// <param name="param"></param>
156 /// <param name="agentID"></param>
157 /// <param name="caps"></param>
158 /// <returns></returns>
159 public string ParcelVoiceInfoRequest(string request, string path, string param,
160 UUID agentID, Caps caps)
161 {
162 // we need to do:
163 // - send channel_uri: as "sip:regionID@m_sipDomain"
164 try
165 {
166 m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}",
167 request, path, param);
168
169
170 // setup response to client
171 Hashtable creds = new Hashtable();
172 creds["channel_uri"] = String.Format("sip:{0}@{1}",
173 m_scene.RegionInfo.RegionID, m_sipDomain);
174
175 string regionName = m_scene.RegionInfo.RegionName;
176 ScenePresence avatar = m_scene.GetScenePresence(agentID);
177 if (null == m_scene.LandChannel) throw new Exception("land data not yet available");
178 LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
179
180 LLSDParcelVoiceInfoResponse parcelVoiceInfo =
181 new LLSDParcelVoiceInfoResponse(regionName, land.LocalID, creds);
182
183 string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
184
185
186 // update region on asterisk-opensim frontend
187 Hashtable requestData = new Hashtable();
188 requestData["admin_password"] = m_asterisk_password;
189 requestData["region"] = m_scene.RegionInfo.RegionID.ToString();
190 if (!String.IsNullOrEmpty(m_confDomain))
191 {
192 requestData["region"] += String.Format("@{0}", m_confDomain);
193 }
194
195 ArrayList SendParams = new ArrayList();
196 SendParams.Add(requestData);
197 XmlRpcRequest updateAccountRequest = new XmlRpcRequest("region_update", SendParams);
198 XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout);
199 Hashtable responseData = (Hashtable) updateAccountResponse.Value;
200
201 if (!responseData.ContainsKey("success")) throw new Exception("region_update call failed");
202
203 bool success = Convert.ToBoolean((string) responseData["success"]);
204 if (!success) throw new Exception("region_update failed");
205
206
207 m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: {0}", r);
208 return r;
209 }
210 catch (Exception e)
211 {
212 m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0}, retry later", e.Message);
213 m_log.DebugFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0} failed", e.ToString());
214
215 return "<llsd>undef</llsd>";
216 }
217 }
218
219 /// <summary>
220 /// Callback for a client request for Voice Account Details
221 /// </summary>
222 /// <param name="request"></param>
223 /// <param name="path"></param>
224 /// <param name="param"></param>
225 /// <param name="agentID"></param>
226 /// <param name="caps"></param>
227 /// <returns></returns>
228 public string ProvisionVoiceAccountRequest(string request, string path, string param,
229 UUID agentID, Caps caps)
230 {
231 // we need to
232 // - get user data from UserProfileCacheService
233 // - generate nonce for user voice account password
234 // - issue XmlRpc request to asterisk opensim front end:
235 // + user: base 64 encoded user name (otherwise SL
236 // client is unhappy)
237 // + password: nonce
238 // - the XmlRpc call to asteris-opensim was successful:
239 // send account details back to client
240 try
241 {
242 m_log.DebugFormat("[ASTERISKVOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
243 request, path, param);
244
245 // get user data & prepare voice account response
246 string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes());
247 voiceUser = voiceUser.Replace('+', '-').Replace('/', '_');
248
249 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
250 if (null == userInfo) throw new Exception("cannot get user details");
251
252 // we generate a nonce everytime
253 string voicePassword = "$1$" + Util.Md5Hash(DateTime.UtcNow.ToLongTimeString() + m_asterisk_salt);
254 LLSDVoiceAccountResponse voiceAccountResponse =
255 new LLSDVoiceAccountResponse(voiceUser, voicePassword);
256 string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
257 m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r);
258
259
260 // update user account on asterisk frontend
261 Hashtable requestData = new Hashtable();
262 requestData["admin_password"] = m_asterisk_password;
263 requestData["username"] = voiceUser;
264 if (!String.IsNullOrEmpty(m_sipDomain))
265 {
266 requestData["username"] += String.Format("@{0}", m_sipDomain);
267 }
268 requestData["password"] = voicePassword;
269
270 ArrayList SendParams = new ArrayList();
271 SendParams.Add(requestData);
272 XmlRpcRequest updateAccountRequest = new XmlRpcRequest("account_update", SendParams);
273 XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout);
274 Hashtable responseData = (Hashtable) updateAccountResponse.Value;
275
276 if (!responseData.ContainsKey("success")) throw new Exception("account_update call failed");
277
278 bool success = Convert.ToBoolean((string) responseData["success"]);
279 if (!success) throw new Exception("account_update failed");
280
281 return r;
282 }
283 catch (Exception e)
284 {
285 m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0}, retry later", e.Message);
286 m_log.DebugFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0} failed", e.ToString());
287
288 return "<llsd>undef</llsd>";
289 }
290 }
291 }
292}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs
deleted file mode 100644
index e4d9b7c..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs
+++ /dev/null
@@ -1,202 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Reflection;
31using OpenMetaverse;
32using log4net;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications.Cache;
36using OpenSim.Framework.Communications.Capabilities;
37using OpenSim.Framework.Servers;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using Caps=OpenSim.Framework.Communications.Capabilities.Caps;
41
42namespace OpenSim.Region.Environment.Modules.Avatar.Voice.SIPVoice
43{
44 public class SIPVoiceModule : IRegionModule
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private static readonly string m_parcelVoiceInfoRequestPath = "0007/";
50 private static readonly string m_provisionVoiceAccountRequestPath = "0008/";
51 private IConfig m_config;
52 private Scene m_scene;
53 private string m_sipDomain;
54
55 #region IRegionModule Members
56
57 public void Initialise(Scene scene, IConfigSource config)
58 {
59 m_scene = scene;
60 m_config = config.Configs["Voice"];
61
62 if (null == m_config || !m_config.GetBoolean("enabled", false))
63 {
64 m_log.Info("[VOICE] plugin disabled");
65 return;
66 }
67 m_log.Info("[VOICE] plugin enabled");
68
69 m_sipDomain = m_config.GetString("sip_domain", String.Empty);
70 if (String.IsNullOrEmpty(m_sipDomain))
71 {
72 m_log.Error("[VOICE] plugin mis-configured: missing sip_domain configuration");
73 m_log.Info("[VOICE] plugin disabled");
74 return;
75 }
76 m_log.InfoFormat("[VOICE] using SIP domain {0}", m_sipDomain);
77
78 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
79 }
80
81 public void PostInitialise()
82 {
83 }
84
85 public void Close()
86 {
87 }
88
89 public string Name
90 {
91 get { return "VoiceModule"; }
92 }
93
94 public bool IsSharedModule
95 {
96 get { return false; }
97 }
98
99 #endregion
100
101 public void OnRegisterCaps(UUID agentID, Caps caps)
102 {
103 m_log.DebugFormat("[VOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
104 string capsBase = "/CAPS/" + caps.CapsObjectPath;
105 caps.RegisterHandler("ParcelVoiceInfoRequest",
106 new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath,
107 delegate(string request, string path, string param,
108 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
109 {
110 return ParcelVoiceInfoRequest(request, path, param,
111 agentID, caps);
112 }));
113 caps.RegisterHandler("ProvisionVoiceAccountRequest",
114 new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath,
115 delegate(string request, string path, string param,
116 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
117 {
118 return ProvisionVoiceAccountRequest(request, path, param,
119 agentID, caps);
120 }));
121 }
122
123 /// <summary>
124 /// Callback for a client request for ParcelVoiceInfo
125 /// </summary>
126 /// <param name="request"></param>
127 /// <param name="path"></param>
128 /// <param name="param"></param>
129 /// <param name="agentID"></param>
130 /// <param name="caps"></param>
131 /// <returns></returns>
132 public string ParcelVoiceInfoRequest(string request, string path, string param,
133 UUID agentID, Caps caps)
134 {
135 try
136 {
137 m_log.DebugFormat("[VOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}", request, path, param);
138
139 // FIXME: get the creds from region file or from config
140 Hashtable creds = new Hashtable();
141
142 creds["channel_uri"] = String.Format("sip:{0}@{1}", agentID, m_sipDomain);
143
144 string regionName = m_scene.RegionInfo.RegionName;
145 ScenePresence avatar = m_scene.GetScenePresence(agentID);
146 if (null == m_scene.LandChannel) throw new Exception("land data not yet available");
147 LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
148
149 LLSDParcelVoiceInfoResponse parcelVoiceInfo =
150 new LLSDParcelVoiceInfoResponse(regionName, land.LocalID, creds);
151
152 string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
153 m_log.DebugFormat("[VOICE][PARCELVOICE]: {0}", r);
154
155 return r;
156 }
157 catch (Exception e)
158 {
159 m_log.ErrorFormat("[CAPS]: {0}, try again later", e.ToString());
160 }
161
162 return null;
163 }
164
165 /// <summary>
166 /// Callback for a client request for Voice Account Details
167 /// </summary>
168 /// <param name="request"></param>
169 /// <param name="path"></param>
170 /// <param name="param"></param>
171 /// <param name="agentID"></param>
172 /// <param name="caps"></param>
173 /// <returns></returns>
174 public string ProvisionVoiceAccountRequest(string request, string path, string param,
175 UUID agentID, Caps caps)
176 {
177 try
178 {
179 m_log.DebugFormat("[VOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
180 request, path, param);
181
182 string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes());
183 voiceUser = voiceUser.Replace('+', '-').Replace('/', '_');
184
185 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
186 if (null == userInfo) throw new Exception("cannot get user details");
187
188 LLSDVoiceAccountResponse voiceAccountResponse =
189 new LLSDVoiceAccountResponse(voiceUser, "$1$" + userInfo.UserProfile.PasswordHash);
190 string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
191 m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r);
192 return r;
193 }
194 catch (Exception e)
195 {
196 m_log.ErrorFormat("[CAPS][PROVISIONVOICE]: {0}, retry later", e.Message);
197 }
198
199 return null;
200 }
201 }
202}
diff --git a/OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs b/OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs
deleted file mode 100644
index 33ccbf4..0000000
--- a/OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs
+++ /dev/null
@@ -1,244 +0,0 @@
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 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 System;
28using System.Collections;
29using System.Collections.Generic;
30using System.Net;
31using System.Net.Sockets;
32using System.Reflection;
33using System.Threading;
34using System.Xml;
35using OpenMetaverse;
36using log4net;
37using Nini.Config;
38using Nwc.XmlRpc;
39using OpenSim.Framework;
40using OpenSim.Framework.Communications.Cache;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.Environment.Modules.Communications.Local
45{
46 public class LocalInterregionComms : IRegionModule, IInterregionCommsOut, IInterregionCommsIn
47 {
48 private bool m_enabled = false;
49
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 private List<Scene> m_sceneList = new List<Scene>();
52
53 #region Events
54 public event ChildAgentUpdateReceived OnChildAgentUpdate;
55
56 #endregion /* Events */
57
58 #region IRegionModule
59
60 public void Initialise(Scene scene, IConfigSource config)
61 {
62 if (m_sceneList.Count == 0)
63 {
64 IConfig startupConfig = config.Configs["Communications"];
65
66 if ((startupConfig != null) && (startupConfig.GetString("InterregionComms", "RESTCommms") == "LocalComms"))
67 {
68 m_log.Debug("[LOCAL COMMS]: Enabling InterregionComms LocalComms module");
69 m_enabled = true;
70 }
71 }
72
73 if (!m_enabled)
74 return;
75
76 Init(scene);
77 }
78
79 public void PostInitialise()
80 {
81 }
82
83 public void Close()
84 {
85 }
86
87 public string Name
88 {
89 get { return "LocalInterregionCommsModule"; }
90 }
91
92 public bool IsSharedModule
93 {
94 get { return true; }
95 }
96 /// <summary>
97 /// Can be called from other modules.
98 /// </summary>
99 /// <param name="scene"></param>
100 public void Init(Scene scene)
101 {
102 if (!m_sceneList.Contains(scene))
103 {
104 lock (m_sceneList)
105 {
106 m_sceneList.Add(scene);
107 if (m_enabled)
108 scene.RegisterModuleInterface<IInterregionCommsOut>(this);
109 scene.RegisterModuleInterface<IInterregionCommsIn>(this);
110 }
111
112 }
113 }
114
115 #endregion /* IRegionModule */
116
117 #region IInterregionComms
118
119 /**
120 * Agent-related communications
121 */
122
123 public bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit)
124 {
125 foreach (Scene s in m_sceneList)
126 {
127 if (s.RegionInfo.RegionHandle == regionHandle)
128 {
129// m_log.DebugFormat("[LOCAL COMMS]: Found region {0} to send SendCreateChildAgent", regionHandle);
130 s.NewUserConnection(aCircuit);
131 return true;
132 }
133 }
134
135// m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for SendCreateChildAgent", regionHandle);
136 return false;
137 }
138
139 public bool SendChildAgentUpdate(ulong regionHandle, AgentData cAgentData)
140 {
141 foreach (Scene s in m_sceneList)
142 {
143 if (s.RegionInfo.RegionHandle == regionHandle)
144 {
145 //m_log.DebugFormat(
146 // "[LOCAL COMMS]: Found region {0} {1} to send ChildAgentUpdate",
147 // s.RegionInfo.RegionName, regionHandle);
148
149 s.IncomingChildAgentDataUpdate(cAgentData);
150 return true;
151 }
152 }
153
154// m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for ChildAgentUpdate", regionHandle);
155 return false;
156 }
157
158 public bool SendChildAgentUpdate(ulong regionHandle, AgentPosition cAgentData)
159 {
160 foreach (Scene s in m_sceneList)
161 {
162 if (s.RegionInfo.RegionHandle == regionHandle)
163 {
164 //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
165 s.IncomingChildAgentDataUpdate(cAgentData);
166 return true;
167 }
168 }
169 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
170 return false;
171 }
172
173 public bool SendReleaseAgent(ulong regionHandle, UUID id, string uri)
174 {
175 //uint x, y;
176 //Utils.LongToUInts(regionHandle, out x, out y);
177 //x = x / Constants.RegionSize;
178 //y = y / Constants.RegionSize;
179 //Console.WriteLine("\n >>> Local SendReleaseAgent " + x + "-" + y);
180 foreach (Scene s in m_sceneList)
181 {
182 if (s.RegionInfo.RegionHandle == regionHandle)
183 {
184 //m_log.Debug("[LOCAL COMMS]: Found region to SendReleaseAgent");
185 return s.IncomingReleaseAgent(id);
186 }
187 }
188 //m_log.Debug("[LOCAL COMMS]: region not found in SendReleaseAgent");
189 return false;
190 }
191
192 public bool SendCloseAgent(ulong regionHandle, UUID id)
193 {
194 //uint x, y;
195 //Utils.LongToUInts(regionHandle, out x, out y);
196 //x = x / Constants.RegionSize;
197 //y = y / Constants.RegionSize;
198 //Console.WriteLine("\n >>> Local SendCloseAgent " + x + "-" + y);
199 foreach (Scene s in m_sceneList)
200 {
201 if (s.RegionInfo.RegionHandle == regionHandle)
202 {
203 //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent");
204 return s.IncomingCloseAgent(id);
205 }
206 }
207 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
208 return false;
209 }
210
211 /**
212 * Object-related communications
213 */
214
215 public bool SendCreateObject(ulong regionHandle, ISceneObject sog)
216 {
217 foreach (Scene s in m_sceneList)
218 {
219 if (s.RegionInfo.RegionHandle == regionHandle)
220 {
221 //m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject");
222 return s.IncomingCreateObject(sog);
223 }
224 }
225 return false;
226 }
227
228 #endregion /* IInterregionComms */
229
230 #region Misc
231
232 public UUID GetRegionID(ulong regionhandle)
233 {
234 foreach (Scene s in m_sceneList)
235 {
236 if (s.RegionInfo.RegionHandle == regionhandle)
237 return s.RegionInfo.RegionID;
238 }
239 // ? weird. should not happen
240 return m_sceneList[0].RegionInfo.RegionID;
241 }
242 #endregion
243 }
244}
diff --git a/OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs b/OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs
deleted file mode 100644
index 95b95ee..0000000
--- a/OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs
+++ /dev/null
@@ -1,960 +0,0 @@
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 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 System;
28using System.Collections;
29using System.Collections.Generic;
30using System.IO;
31using System.Net;
32using System.Net.Sockets;
33using System.Reflection;
34using System.Threading;
35using System.Xml;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using log4net;
39using Nini.Config;
40using Nwc.XmlRpc;
41using OpenSim.Framework;
42using OpenSim.Framework.Communications;
43using OpenSim.Framework.Communications.Cache;
44using OpenSim.Framework.Servers;
45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Framework.Scenes.Hypergrid;
48using OpenSim.Region.Environment.Modules.Communications.Local;
49
50namespace OpenSim.Region.Environment.Modules.Communications.REST
51{
52 public class RESTInterregionComms : IRegionModule, IInterregionCommsOut
53 {
54 private static bool initialized = false;
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 protected bool m_enabled = false;
58 protected Scene m_aScene;
59 // RESTInterregionComms does not care about local regions; it delegates that to the Local module
60 protected LocalInterregionComms m_localBackend;
61
62 protected CommunicationsManager m_commsManager;
63
64 #region IRegionModule
65
66 public virtual void Initialise(Scene scene, IConfigSource config)
67 {
68 if (!initialized)
69 {
70 initialized = true;
71 IConfig startupConfig = config.Configs["Communications"];
72
73 if ((startupConfig == null)
74 || (startupConfig != null)
75 && (startupConfig.GetString("InterregionComms", "RESTComms") == "RESTComms"))
76 {
77 m_log.Info("[REST COMMS]: Enabling InterregionComms RESTComms module");
78 m_enabled = true;
79 InitOnce(scene);
80 }
81 }
82
83 if (!m_enabled)
84 return;
85
86 InitEach(scene);
87
88 }
89
90 public virtual void PostInitialise()
91 {
92 if (m_enabled)
93 AddHTTPHandlers();
94 }
95
96 public virtual void Close()
97 {
98 }
99
100 public virtual string Name
101 {
102 get { return "RESTInterregionCommsModule"; }
103 }
104
105 public virtual bool IsSharedModule
106 {
107 get { return true; }
108 }
109
110 protected virtual void InitEach(Scene scene)
111 {
112 m_localBackend.Init(scene);
113 scene.RegisterModuleInterface<IInterregionCommsOut>(this);
114 }
115
116 protected virtual void InitOnce(Scene scene)
117 {
118 m_localBackend = new LocalInterregionComms();
119 m_commsManager = scene.CommsManager;
120 m_aScene = scene;
121 }
122
123 protected virtual void AddHTTPHandlers()
124 {
125 m_aScene.CommsManager.HttpServer.AddHTTPHandler("/agent/", AgentHandler);
126 m_aScene.CommsManager.HttpServer.AddHTTPHandler("/object/", ObjectHandler);
127 }
128
129 #endregion /* IRegionModule */
130
131 #region IInterregionComms
132
133 /**
134 * Agent-related communications
135 */
136
137 public bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit)
138 {
139 // Try local first
140 if (m_localBackend.SendCreateChildAgent(regionHandle, aCircuit))
141 return true;
142
143 // else do the remote thing
144 RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle);
145 if (regInfo != null)
146 {
147 SendUserInformation(regInfo, aCircuit);
148
149 return DoCreateChildAgentCall(regInfo, aCircuit);
150 }
151 //else
152 // m_log.Warn("[REST COMMS]: Region not found " + regionHandle);
153 return false;
154 }
155
156 public bool SendChildAgentUpdate(ulong regionHandle, AgentData cAgentData)
157 {
158 // Try local first
159 if (m_localBackend.SendChildAgentUpdate(regionHandle, cAgentData))
160 return true;
161
162 // else do the remote thing
163 RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle);
164 if (regInfo != null)
165 {
166 return DoChildAgentUpdateCall(regInfo, cAgentData);
167 }
168 //else
169 // m_log.Warn("[REST COMMS]: Region not found " + regionHandle);
170 return false;
171
172 }
173
174 public bool SendChildAgentUpdate(ulong regionHandle, AgentPosition cAgentData)
175 {
176 // Try local first
177 if (m_localBackend.SendChildAgentUpdate(regionHandle, cAgentData))
178 return true;
179
180 // else do the remote thing
181 RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle);
182 if (regInfo != null)
183 {
184 return DoChildAgentUpdateCall(regInfo, cAgentData);
185 }
186 //else
187 // m_log.Warn("[REST COMMS]: Region not found " + regionHandle);
188 return false;
189
190 }
191
192 public bool SendReleaseAgent(ulong regionHandle, UUID id, string uri)
193 {
194 // Try local first
195 if (m_localBackend.SendReleaseAgent(regionHandle, id, uri))
196 return true;
197
198 // else do the remote thing
199 return DoReleaseAgentCall(regionHandle, id, uri);
200 }
201
202 public bool SendCloseAgent(ulong regionHandle, UUID id)
203 {
204 // Try local first
205 if (m_localBackend.SendCloseAgent(regionHandle, id))
206 return true;
207
208 // else do the remote thing
209 RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle);
210 if (regInfo != null)
211 {
212 return DoCloseAgentCall(regInfo, id);
213 }
214 //else
215 // m_log.Warn("[REST COMMS]: Region not found " + regionHandle);
216 return false;
217 }
218
219 /**
220 * Object-related communications
221 */
222
223 public bool SendCreateObject(ulong regionHandle, ISceneObject sog)
224 {
225 // Try local first
226 ISceneObject sogClone = sog.CloneForNewScene();
227 if (m_localBackend.SendCreateObject(regionHandle, sogClone))
228 {
229 //m_log.Debug("[REST COMMS]: LocalBackEnd SendCreateObject succeeded");
230 return true;
231 }
232
233 // else do the remote thing
234 RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle);
235 if (regInfo != null)
236 {
237 return DoCreateObjectCall(regInfo, sog);
238 }
239 //else
240 // m_log.Warn("[REST COMMS]: Region not found " + regionHandle);
241 return false;
242 }
243
244 #endregion /* IInterregionComms */
245
246 #region DoWork functions for the above public interface
247
248 //-------------------------------------------------------------------
249 // Internal functions for the above public interface
250 //-------------------------------------------------------------------
251
252 protected bool DoCreateChildAgentCall(RegionInfo region, AgentCircuitData aCircuit)
253 {
254 // Eventually, we want to use a caps url instead of the agentID
255 string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + aCircuit.AgentID + "/";
256 //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri);
257
258 WebRequest AgentCreateRequest = WebRequest.Create(uri);
259 AgentCreateRequest.Method = "POST";
260 AgentCreateRequest.ContentType = "application/json";
261 AgentCreateRequest.Timeout = 10000;
262
263 // Fill it in
264 OSDMap args = null;
265 try
266 {
267 args = aCircuit.PackAgentCircuitData();
268 }
269 catch (Exception e)
270 {
271 m_log.Debug("[REST COMMS]: PackAgentCircuitData failed with exception: " + e.Message);
272 }
273 // Add the regionhandle of the destination region
274 ulong regionHandle = GetRegionHandle(region.RegionHandle);
275 args["destination_handle"] = OSD.FromString(regionHandle.ToString());
276
277 string strBuffer = "";
278 byte[] buffer = new byte[1];
279 try
280 {
281 strBuffer = OSDParser.SerializeJsonString(args);
282 System.Text.UTF8Encoding str = new System.Text.UTF8Encoding();
283 buffer = str.GetBytes(strBuffer);
284
285 }
286 catch (Exception e)
287 {
288 m_log.WarnFormat("[OSG2]: Exception thrown on serialization of ChildCreate: {0}", e.Message);
289 // ignore. buffer will be empty, caller should check.
290 }
291
292 Stream os = null;
293 try
294 { // send the Post
295 AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send
296 os = AgentCreateRequest.GetRequestStream();
297 os.Write(buffer, 0, strBuffer.Length); //Send it
298 os.Close();
299 //m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri);
300 }
301 //catch (WebException ex)
302 catch
303 {
304 //m_log.InfoFormat("[REST COMMS]: Bad send on ChildAgentUpdate {0}", ex.Message);
305
306 return false;
307 }
308
309 // Let's wait for the response
310 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
311
312 try
313 {
314 WebResponse webResponse = AgentCreateRequest.GetResponse();
315 if (webResponse == null)
316 {
317 m_log.Info("[REST COMMS]: Null reply on DoCreateChildAgentCall post");
318 }
319
320 StreamReader sr = new StreamReader(webResponse.GetResponseStream());
321 //reply = sr.ReadToEnd().Trim();
322 sr.ReadToEnd().Trim();
323 sr.Close();
324 //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply);
325
326 }
327 catch (WebException ex)
328 {
329 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex.Message);
330 // ignore, really
331 }
332
333 return true;
334
335 }
336
337 protected bool DoChildAgentUpdateCall(RegionInfo region, IAgentData cAgentData)
338 {
339 // Eventually, we want to use a caps url instead of the agentID
340 string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + cAgentData.AgentID + "/";
341 //Console.WriteLine(" >>> DoChildAgentUpdateCall <<< " + uri);
342
343 WebRequest ChildUpdateRequest = WebRequest.Create(uri);
344 ChildUpdateRequest.Method = "PUT";
345 ChildUpdateRequest.ContentType = "application/json";
346 ChildUpdateRequest.Timeout = 10000;
347
348 // Fill it in
349 OSDMap args = null;
350 try
351 {
352 args = cAgentData.PackUpdateMessage();
353 }
354 catch (Exception e)
355 {
356 m_log.Debug("[REST COMMS]: PackUpdateMessage failed with exception: " + e.Message);
357 }
358 // Add the regionhandle of the destination region
359 ulong regionHandle = GetRegionHandle(region.RegionHandle);
360 args["destination_handle"] = OSD.FromString(regionHandle.ToString());
361
362 string strBuffer = "";
363 byte[] buffer = new byte[1];
364 try
365 {
366 strBuffer = OSDParser.SerializeJsonString(args);
367 System.Text.UTF8Encoding str = new System.Text.UTF8Encoding();
368 buffer = str.GetBytes(strBuffer);
369
370 }
371 catch (Exception e)
372 {
373 m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of ChildUpdate: {0}", e.Message);
374 // ignore. buffer will be empty, caller should check.
375 }
376
377 Stream os = null;
378 try
379 { // send the Post
380 ChildUpdateRequest.ContentLength = buffer.Length; //Count bytes to send
381 os = ChildUpdateRequest.GetRequestStream();
382 os.Write(buffer, 0, strBuffer.Length); //Send it
383 os.Close();
384 //m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri);
385 }
386 //catch (WebException ex)
387 catch
388 {
389 //m_log.InfoFormat("[REST COMMS]: Bad send on ChildAgentUpdate {0}", ex.Message);
390
391 return false;
392 }
393
394 // Let's wait for the response
395 //m_log.Info("[REST COMMS]: Waiting for a reply after ChildAgentUpdate");
396
397 try
398 {
399 WebResponse webResponse = ChildUpdateRequest.GetResponse();
400 if (webResponse == null)
401 {
402 m_log.Info("[REST COMMS]: Null reply on ChilAgentUpdate post");
403 }
404
405 StreamReader sr = new StreamReader(webResponse.GetResponseStream());
406 //reply = sr.ReadToEnd().Trim();
407 sr.ReadToEnd().Trim();
408 sr.Close();
409 //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply);
410
411 }
412 catch (WebException ex)
413 {
414 m_log.InfoFormat("[REST COMMS]: exception on reply of ChilAgentUpdate {0}", ex.Message);
415 // ignore, really
416 }
417
418 return true;
419 }
420
421 protected bool DoReleaseAgentCall(ulong regionHandle, UUID id, string uri)
422 {
423 //Console.WriteLine(" >>> DoReleaseAgentCall <<< " + uri);
424
425 WebRequest request = WebRequest.Create(uri);
426 request.Method = "DELETE";
427 request.Timeout = 10000;
428
429 try
430 {
431 WebResponse webResponse = request.GetResponse();
432 if (webResponse == null)
433 {
434 m_log.Info("[REST COMMS]: Null reply on agent get ");
435 }
436
437 StreamReader sr = new StreamReader(webResponse.GetResponseStream());
438 //reply = sr.ReadToEnd().Trim();
439 sr.ReadToEnd().Trim();
440 sr.Close();
441 //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply);
442
443 }
444 catch (WebException ex)
445 {
446 m_log.InfoFormat("[REST COMMS]: exception on reply of agent get {0}", ex.Message);
447 // ignore, really
448 }
449
450 return true;
451 }
452
453 protected bool DoCloseAgentCall(RegionInfo region, UUID id)
454 {
455 string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + id + "/" + region.RegionHandle.ToString() +"/";
456
457 //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri);
458
459 WebRequest request = WebRequest.Create(uri);
460 request.Method = "DELETE";
461 request.Timeout = 10000;
462
463 try
464 {
465 WebResponse webResponse = request.GetResponse();
466 if (webResponse == null)
467 {
468 m_log.Info("[REST COMMS]: Null reply on agent get ");
469 }
470
471 StreamReader sr = new StreamReader(webResponse.GetResponseStream());
472 //reply = sr.ReadToEnd().Trim();
473 sr.ReadToEnd().Trim();
474 sr.Close();
475 //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply);
476
477 }
478 catch (WebException ex)
479 {
480 m_log.InfoFormat("[REST COMMS]: exception on reply of agent get {0}", ex.Message);
481 // ignore, really
482 }
483
484 return true;
485 }
486
487 protected bool DoCreateObjectCall(RegionInfo region, ISceneObject sog)
488 {
489 ulong regionHandle = GetRegionHandle(region.RegionHandle);
490 string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/object/" + sog.UUID + "/" + regionHandle.ToString() + "/";
491 //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri);
492
493 WebRequest ObjectCreateRequest = WebRequest.Create(uri);
494 ObjectCreateRequest.Method = "POST";
495 ObjectCreateRequest.ContentType = "text/xml";
496 ObjectCreateRequest.Timeout = 10000;
497
498 OSDMap args = new OSDMap(2);
499 args["sog"] = OSD.FromString(sog.ToXmlString2());
500 args["extra"] = OSD.FromString(sog.ExtraToXmlString());
501 if (m_aScene.m_allowScriptCrossings)
502 {
503 string state = sog.GetStateSnapshot();
504 if (state.Length > 0)
505 args["state"] = OSD.FromString(state);
506 }
507
508 string strBuffer = "";
509 byte[] buffer = new byte[1];
510 try
511 {
512 strBuffer = OSDParser.SerializeJsonString(args);
513 System.Text.UTF8Encoding str = new System.Text.UTF8Encoding();
514 buffer = str.GetBytes(strBuffer);
515
516 }
517 catch (Exception e)
518 {
519 m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of CreateObject: {0}", e.Message);
520 // ignore. buffer will be empty, caller should check.
521 }
522
523 Stream os = null;
524 try
525 { // send the Post
526 ObjectCreateRequest.ContentLength = buffer.Length; //Count bytes to send
527 os = ObjectCreateRequest.GetRequestStream();
528 os.Write(buffer, 0, strBuffer.Length); //Send it
529 os.Close();
530 m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri);
531 }
532 //catch (WebException ex)
533 catch
534 {
535 // m_log.InfoFormat("[REST COMMS]: Bad send on CreateObject {0}", ex.Message);
536
537 return false;
538 }
539
540 // Let's wait for the response
541 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
542
543 try
544 {
545 WebResponse webResponse = ObjectCreateRequest.GetResponse();
546 if (webResponse == null)
547 {
548 m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post");
549 }
550
551 StreamReader sr = new StreamReader(webResponse.GetResponseStream());
552 //reply = sr.ReadToEnd().Trim();
553 sr.ReadToEnd().Trim();
554 sr.Close();
555 //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply);
556
557 }
558 catch (WebException ex)
559 {
560 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message);
561 // ignore, really
562 }
563
564 return true;
565
566 }
567
568 #endregion /* Do Work */
569
570 #region Incoming calls from remote instances
571
572 /**
573 * Agent-related incoming calls
574 */
575
576 public Hashtable AgentHandler(Hashtable request)
577 {
578 //m_log.Debug("[CONNECTION DEBUGGING]: AgentHandler Called");
579
580 //Console.WriteLine("---------------------------");
581 //Console.WriteLine(" >> uri=" + request["uri"]);
582 //Console.WriteLine(" >> content-type=" + request["content-type"]);
583 //Console.WriteLine(" >> http-method=" + request["http-method"]);
584 //Console.WriteLine("---------------------------\n");
585
586 Hashtable responsedata = new Hashtable();
587 responsedata["content_type"] = "text/html";
588
589 UUID agentID;
590 string action;
591 ulong regionHandle;
592 if (!GetParams((string)request["uri"], out agentID, out regionHandle, out action))
593 {
594 m_log.InfoFormat("[REST COMMS]: Invalid parameters for agent message {0}", request["uri"]);
595 responsedata["int_response_code"] = 404;
596 responsedata["str_response_string"] = "false";
597
598 return responsedata;
599 }
600
601 // Next, let's parse the verb
602 string method = (string)request["http-method"];
603 if (method.Equals("PUT"))
604 {
605 DoAgentPut(request, responsedata);
606 return responsedata;
607 }
608 else if (method.Equals("POST"))
609 {
610 DoAgentPost(request, responsedata, agentID);
611 return responsedata;
612 }
613 else if (method.Equals("DELETE"))
614 {
615 DoAgentDelete(request, responsedata, agentID, action, regionHandle);
616
617 return responsedata;
618 }
619 else
620 {
621 m_log.InfoFormat("[REST COMMS]: method {0} not supported in agent message", method);
622 responsedata["int_response_code"] = 404;
623 responsedata["str_response_string"] = "false";
624
625 return responsedata;
626 }
627
628 }
629
630 protected OSDMap GetOSDMap(Hashtable request)
631 {
632 OSDMap args = null;
633 try
634 {
635 OSD buffer;
636 // We should pay attention to the content-type, but let's assume we know it's Json
637 buffer = OSDParser.DeserializeJson((string)request["body"]);
638 if (buffer.Type == OSDType.Map)
639 {
640 args = (OSDMap)buffer;
641 return args;
642 }
643 else
644 {
645 // uh?
646 m_log.Debug("[REST COMMS]: Got OSD of type " + buffer.Type.ToString());
647 return null;
648 }
649 }
650 catch (Exception ex)
651 {
652 m_log.InfoFormat("[REST COMMS]: exception on parse of REST message {0}", ex.Message);
653 return null;
654 }
655 }
656
657 protected virtual void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id)
658 {
659 OSDMap args = GetOSDMap(request);
660 if (args == null)
661 {
662 responsedata["int_response_code"] = 400;
663 responsedata["str_response_string"] = "false";
664 return;
665 }
666
667 // retrieve the regionhandle
668 ulong regionhandle = 0;
669 if (args["destination_handle"] != null)
670 UInt64.TryParse(args["destination_handle"].AsString(), out regionhandle);
671
672 AgentCircuitData aCircuit = new AgentCircuitData();
673 try
674 {
675 aCircuit.UnpackAgentCircuitData(args);
676 }
677 catch (Exception ex)
678 {
679 m_log.InfoFormat("[REST COMMS]: exception on unpacking ChildCreate message {0}", ex.Message);
680 return;
681 }
682
683 // This is the meaning of POST agent
684 AdjustUserInformation(aCircuit);
685 bool result = m_localBackend.SendCreateChildAgent(regionhandle, aCircuit);
686
687 responsedata["int_response_code"] = 200;
688 responsedata["str_response_string"] = result.ToString();
689 }
690
691 protected virtual void DoAgentPut(Hashtable request, Hashtable responsedata)
692 {
693 OSDMap args = GetOSDMap(request);
694 if (args == null)
695 {
696 responsedata["int_response_code"] = 400;
697 responsedata["str_response_string"] = "false";
698 return;
699 }
700
701 // retrieve the regionhandle
702 ulong regionhandle = 0;
703 if (args["destination_handle"] != null)
704 UInt64.TryParse(args["destination_handle"].AsString(), out regionhandle);
705
706 string messageType;
707 if (args["message_type"] != null)
708 messageType = args["message_type"].AsString();
709 else
710 {
711 m_log.Warn("[REST COMMS]: Agent Put Message Type not found. ");
712 messageType = "AgentData";
713 }
714
715 bool result = true;
716 if ("AgentData".Equals(messageType))
717 {
718 AgentData agent = new AgentData();
719 try
720 {
721 agent.UnpackUpdateMessage(args);
722 }
723 catch (Exception ex)
724 {
725 m_log.InfoFormat("[REST COMMS]: exception on unpacking ChildAgentUpdate message {0}", ex.Message);
726 return;
727 }
728 //agent.Dump();
729 // This is one of the meanings of PUT agent
730 result = m_localBackend.SendChildAgentUpdate(regionhandle, agent);
731
732 }
733 else if ("AgentPosition".Equals(messageType))
734 {
735 AgentPosition agent = new AgentPosition();
736 try
737 {
738 agent.UnpackUpdateMessage(args);
739 }
740 catch (Exception ex)
741 {
742 m_log.InfoFormat("[REST COMMS]: exception on unpacking ChildAgentUpdate message {0}", ex.Message);
743 return;
744 }
745 //agent.Dump();
746 // This is one of the meanings of PUT agent
747 result = m_localBackend.SendChildAgentUpdate(regionhandle, agent);
748
749 }
750
751
752
753 responsedata["int_response_code"] = 200;
754 responsedata["str_response_string"] = result.ToString();
755 }
756
757 protected virtual void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, ulong regionHandle)
758 {
759 //Console.WriteLine(" >>> DoDelete action:" + action + "; regionHandle:" + regionHandle);
760
761 if (action.Equals("release"))
762 m_localBackend.SendReleaseAgent(regionHandle, id, "");
763 else
764 m_localBackend.SendCloseAgent(regionHandle, id);
765
766 responsedata["int_response_code"] = 200;
767 responsedata["str_response_string"] = "OpenSim agent " + id.ToString();
768 }
769
770 /**
771 * Object-related incoming calls
772 */
773
774 public Hashtable ObjectHandler(Hashtable request)
775 {
776 //m_log.Debug("[CONNECTION DEBUGGING]: ObjectHandler Called");
777
778 //Console.WriteLine("---------------------------");
779 //Console.WriteLine(" >> uri=" + request["uri"]);
780 //Console.WriteLine(" >> content-type=" + request["content-type"]);
781 //Console.WriteLine(" >> http-method=" + request["http-method"]);
782 //Console.WriteLine("---------------------------\n");
783
784 Hashtable responsedata = new Hashtable();
785 responsedata["content_type"] = "text/html";
786
787 UUID objectID;
788 string action;
789 ulong regionHandle;
790 if (!GetParams((string)request["uri"], out objectID, out regionHandle, out action))
791 {
792 m_log.InfoFormat("[REST COMMS]: Invalid parameters for object message {0}", request["uri"]);
793 responsedata["int_response_code"] = 404;
794 responsedata["str_response_string"] = "false";
795
796 return responsedata;
797 }
798
799 // Next, let's parse the verb
800 string method = (string)request["http-method"];
801 if (method.Equals("POST"))
802 {
803 DoObjectPost(request, responsedata, regionHandle);
804 return responsedata;
805 }
806 //else if (method.Equals("PUT"))
807 //{
808 // DoObjectPut(request, responsedata, agentID);
809 // return responsedata;
810 //}
811 //else if (method.Equals("DELETE"))
812 //{
813 // DoObjectDelete(request, responsedata, agentID, action, regionHandle);
814 // return responsedata;
815 //}
816 else
817 {
818 m_log.InfoFormat("[REST COMMS]: method {0} not supported in object message", method);
819 responsedata["int_response_code"] = 404;
820 responsedata["str_response_string"] = "false";
821
822 return responsedata;
823 }
824
825 }
826
827 protected virtual void DoObjectPost(Hashtable request, Hashtable responsedata, ulong regionhandle)
828 {
829 OSDMap args = GetOSDMap(request);
830 if (args == null)
831 {
832 responsedata["int_response_code"] = 400;
833 responsedata["str_response_string"] = "false";
834 return;
835 }
836
837 string sogXmlStr = "", extraStr = "", stateXmlStr = "";
838 if (args["sog"] != null)
839 sogXmlStr = args["sog"].AsString();
840 if (args["extra"] != null)
841 extraStr = args["extra"].AsString();
842
843 UUID regionID = m_localBackend.GetRegionID(regionhandle);
844 SceneObjectGroup sog = null;
845 try
846 {
847 sog = new SceneObjectGroup(sogXmlStr);
848 sog.ExtraFromXmlString(extraStr);
849 }
850 catch (Exception ex)
851 {
852 m_log.InfoFormat("[REST COMMS]: exception on deserializing scene object {0}", ex.Message);
853 responsedata["int_response_code"] = 400;
854 responsedata["str_response_string"] = "false";
855 return;
856 }
857
858 if ((args["state"] != null) && m_aScene.m_allowScriptCrossings)
859 {
860 stateXmlStr = args["state"].AsString();
861 if (stateXmlStr != "")
862 {
863 try
864 {
865 sog.SetState(stateXmlStr, regionID);
866 }
867 catch (Exception ex)
868 {
869 m_log.InfoFormat("[REST COMMS]: exception on setting state for scene object {0}", ex.Message);
870
871 }
872 }
873 }
874 // This is the meaning of POST object
875 bool result = m_localBackend.SendCreateObject(regionhandle, sog);
876
877 responsedata["int_response_code"] = 200;
878 responsedata["str_response_string"] = result.ToString();
879 }
880
881 #endregion
882
883 #region Misc
884
885 /// <summary>
886 /// Extract the param from an uri.
887 /// </summary>
888 /// <param name="uri">Something like this: /agent/uuid/ or /agent/uuid/handle/release</param>
889 /// <param name="uri">uuid on uuid field</param>
890 /// <param name="action">optional action</param>
891 protected bool GetParams(string uri, out UUID uuid, out ulong regionHandle, out string action)
892 {
893 uuid = UUID.Zero;
894 action = "";
895 regionHandle = 0;
896
897 uri = uri.Trim(new char[] { '/' });
898 string[] parts = uri.Split('/');
899 if (parts.Length <= 1)
900 {
901 return false;
902 }
903 else
904 {
905 if (!UUID.TryParse(parts[1], out uuid))
906 return false;
907
908 if (parts.Length >= 3)
909 UInt64.TryParse(parts[2], out regionHandle);
910 if (parts.Length >= 4)
911 action = parts[3];
912
913 return true;
914 }
915 }
916
917 #endregion Misc
918
919 #region Hyperlinks
920
921 protected virtual ulong GetRegionHandle(ulong handle)
922 {
923 if (m_aScene.SceneGridService is HGSceneCommunicationService)
924 return ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.FindRegionHandle(handle);
925
926 return handle;
927 }
928
929 protected virtual bool IsHyperlink(ulong handle)
930 {
931 if (m_aScene.SceneGridService is HGSceneCommunicationService)
932 return ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.IsHyperlinkRegion(handle);
933
934 return false;
935 }
936
937 protected virtual void SendUserInformation(RegionInfo regInfo, AgentCircuitData aCircuit)
938 {
939 try
940 {
941 //if (IsHyperlink(regInfo.RegionHandle))
942 if (m_aScene.SceneGridService is HGSceneCommunicationService)
943 {
944 ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.SendUserInformation(regInfo, aCircuit);
945 }
946 }
947 catch // Bad cast
948 { }
949
950 }
951
952 protected virtual void AdjustUserInformation(AgentCircuitData aCircuit)
953 {
954 if (m_aScene.SceneGridService is HGSceneCommunicationService)
955 ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.AdjustUserInformation(aCircuit);
956 }
957 #endregion /* Hyperlinks */
958
959 }
960}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs
deleted file mode 100644
index 9695fb8..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs
+++ /dev/null
@@ -1,161 +0,0 @@
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 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 */
27
28#region Header
29
30// AuraMetaEntity.cs created with MonoDevelop
31// User: bongiojp at 3:03 PM 8/6/2008
32//
33// To change standard headers go to Edit->Preferences->Coding->Standard Headers
34//
35
36#endregion Header
37
38using System;
39using System.Collections.Generic;
40using System.Drawing;
41
42using OpenMetaverse;
43
44using Nini.Config;
45
46using OpenSim.Framework;
47using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Physics.Manager;
50
51using log4net;
52
53namespace OpenSim.Region.Environment.Modules.ContentManagement
54{
55 public class AuraMetaEntity : PointMetaEntity
56 {
57 #region Constructors
58
59 //transparency of root part, NOT particle system. Should probably add support for changing particle system transparency.
60 public AuraMetaEntity(Scene scene, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale)
61 : base(scene, groupPos, transparency)
62 {
63 SetAura(color, scale);
64 }
65
66 public AuraMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale)
67 : base(scene, uuid, groupPos, transparency)
68 {
69 SetAura(color, scale);
70 }
71
72 #endregion Constructors
73
74 #region Private Methods
75
76 private float Average(Vector3 values)
77 {
78 return (values.X + values.Y + values.Z)/3f;
79 }
80
81 #endregion Private Methods
82
83 #region Public Methods
84
85 public void SetAura(Vector3 color, Vector3 scale)
86 {
87 SetAura(color, Average(scale) * 2.0f);
88 }
89
90 public void SetAura(Vector3 color, float radius)
91 {
92 SceneObjectPart From = m_Entity.RootPart;
93
94 //m_log.Debug("[META ENTITY] BEFORE: radius = " + radius);
95 float burstRadius = 0.1f;
96 Primitive.ParticleSystem.SourcePattern patternFlags = Primitive.ParticleSystem.SourcePattern.None;
97 float age = 1.5f;
98 float burstRate = 0.4f;
99 if (radius >= 8.0f)
100 {
101 //float sizeOfObject = radius / 2.0f;
102 burstRadius = (radius - 8.0f)/3f;
103 burstRate = 1.5f;
104 radius = 7.99f;
105 patternFlags = Primitive.ParticleSystem.SourcePattern.Explode;
106 age = 4.0f;
107 }
108 SetAura(From, color, radius, burstRadius, age, burstRate, patternFlags);
109 }
110
111 public void SetAura(SceneObjectPart From, Vector3 color, float radius, float burstRadius, float age, float burstRate, Primitive.ParticleSystem.SourcePattern patternFlags)
112 {
113 Primitive.ParticleSystem prules = new Primitive.ParticleSystem();
114 //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive |
115 // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS
116 //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam |
117 // Primitive.ParticleSystem.ParticleDataFlags.TargetPos;
118 prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR
119 prules.PartStartColor.G = color.Y;
120 prules.PartStartColor.B = color.Z;
121 prules.PartStartColor.A = 0.5f; //PSYS_PART_START_ALPHA, transparency
122 prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR
123 prules.PartEndColor.G = color.Y;
124 prules.PartEndColor.B = color.Z;
125 prules.PartEndColor.A = 0.5f; //PSYS_PART_END_ALPHA, transparency
126 /*prules.PartStartScaleX = 0.5f; //PSYS_PART_START_SCALE
127 prules.PartStartScaleY = 0.5f;
128 prules.PartEndScaleX = 0.5f; //PSYS_PART_END_SCALE
129 prules.PartEndScaleY = 0.5f;
130 */
131 prules.PartStartScaleX = radius; //PSYS_PART_START_SCALE
132 prules.PartStartScaleY = radius;
133 prules.PartEndScaleX = radius; //PSYS_PART_END_SCALE
134 prules.PartEndScaleY = radius;
135 prules.PartMaxAge = age; //PSYS_PART_MAX_AGE
136 prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL
137 prules.PartAcceleration.Y = 0.0f;
138 prules.PartAcceleration.Z = 0.0f;
139 prules.Pattern = patternFlags; //PSYS_SRC_PATTERN
140 //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank
141 prules.BurstRate = burstRate; //PSYS_SRC_BURST_RATE
142 prules.BurstPartCount = 2; //PSYS_SRC_BURST_PART_COUNT
143 //prules.BurstRadius = radius; //PSYS_SRC_BURST_RADIUS
144 prules.BurstRadius = burstRadius; //PSYS_SRC_BURST_RADIUS
145 prules.BurstSpeedMin = 0.001f; //PSYS_SRC_BURST_SPEED_MIN
146 prules.BurstSpeedMax = 0.001f; //PSYS_SRC_BURST_SPEED_MAX
147 prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE
148 //prules.Target = To; //PSYS_SRC_TARGET_KEY
149 prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA
150 prules.AngularVelocity.Y = 0.0f;
151 prules.AngularVelocity.Z = 0.0f;
152 prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN
153 prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END
154
155 prules.CRC = 1; //activates the particle system??
156 From.AddNewParticleSystem(prules);
157 }
158
159 #endregion Public Methods
160 }
161}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs
deleted file mode 100644
index 3b1a45e..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs
+++ /dev/null
@@ -1,139 +0,0 @@
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 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 */
27
28#region Header
29
30// BeamMetaEntity.cs created with MonoDevelop
31// User: bongiojp at 3:03 PM 8/6/2008
32//
33// To change standard headers go to Edit->Preferences->Coding->Standard Headers
34//
35
36#endregion Header
37
38using System;
39using System.Collections.Generic;
40using System.Drawing;
41
42using OpenMetaverse;
43
44using Nini.Config;
45
46using OpenSim.Framework;
47using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Physics.Manager;
50
51using log4net;
52
53namespace OpenSim.Region.Environment.Modules.ContentManagement
54{
55 public class BeamMetaEntity : PointMetaEntity
56 {
57 #region Constructors
58
59 public BeamMetaEntity(Scene scene, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color)
60 : base(scene, groupPos, transparency)
61 {
62 SetBeamToUUID(To, color);
63 }
64
65 public BeamMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color)
66 : base(scene, uuid, groupPos, transparency)
67 {
68 SetBeamToUUID(To, color);
69 }
70
71 #endregion Constructors
72
73 #region Public Methods
74
75 public void SetBeamToUUID(SceneObjectPart To, Vector3 color)
76 {
77 SceneObjectPart From = m_Entity.RootPart;
78 //Scale size of particles to distance objects are apart (for better visibility)
79 Vector3 FromPos = From.GetWorldPosition();
80 Vector3 ToPos = From.GetWorldPosition();
81 // UUID toUUID = To.UUID;
82 float distance = (float) (Math.Sqrt(Math.Pow(FromPos.X-ToPos.X, 2) +
83 Math.Pow(FromPos.X-ToPos.Y, 2) +
84 Math.Pow(FromPos.X-ToPos.Z, 2)
85 )
86 );
87 //float rate = (float) (distance/4f);
88 float rate = 0.5f;
89 float scale = (float) (distance/128f);
90 float speed = (float) (2.0f - distance/128f);
91
92 SetBeamToUUID(From, To, color, rate, scale, speed);
93 }
94
95 public void SetBeamToUUID(SceneObjectPart From, SceneObjectPart To, Vector3 color, float rate, float scale, float speed)
96 {
97 Primitive.ParticleSystem prules = new Primitive.ParticleSystem();
98 //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive |
99 // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS
100 prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam |
101 Primitive.ParticleSystem.ParticleDataFlags.TargetPos;
102 prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR
103 prules.PartStartColor.G = color.Y;
104 prules.PartStartColor.B = color.Z;
105 prules.PartStartColor.A = 1.0f; //PSYS_PART_START_ALPHA, transparency
106 prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR
107 prules.PartEndColor.G = color.Y;
108 prules.PartEndColor.B = color.Z;
109 prules.PartEndColor.A = 1.0f; //PSYS_PART_END_ALPHA, transparency
110 prules.PartStartScaleX = scale; //PSYS_PART_START_SCALE
111 prules.PartStartScaleY = scale;
112 prules.PartEndScaleX = scale; //PSYS_PART_END_SCALE
113 prules.PartEndScaleY = scale;
114 prules.PartMaxAge = 1.0f; //PSYS_PART_MAX_AGE
115 prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL
116 prules.PartAcceleration.Y = 0.0f;
117 prules.PartAcceleration.Z = 0.0f;
118 //prules.Pattern = Primitive.ParticleSystem.SourcePattern.Explode; //PSYS_SRC_PATTERN
119 //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank
120 prules.BurstRate = rate; //PSYS_SRC_BURST_RATE
121 prules.BurstPartCount = 1; //PSYS_SRC_BURST_PART_COUNT
122 prules.BurstRadius = 0.5f; //PSYS_SRC_BURST_RADIUS
123 prules.BurstSpeedMin = speed; //PSYS_SRC_BURST_SPEED_MIN
124 prules.BurstSpeedMax = speed; //PSYS_SRC_BURST_SPEED_MAX
125 prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE
126 prules.Target = To.UUID; //PSYS_SRC_TARGET_KEY
127 prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA
128 prules.AngularVelocity.Y = 0.0f;
129 prules.AngularVelocity.Z = 0.0f;
130 prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN
131 prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END
132
133 prules.CRC = 1; //activates the particle system??
134 From.AddNewParticleSystem(prules);
135 }
136
137 #endregion Public Methods
138 }
139}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs
deleted file mode 100644
index 5a86d48..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs
+++ /dev/null
@@ -1,757 +0,0 @@
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 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 */
27
28#region Header
29
30// CMController.cs
31// User: bongiojp
32//
33
34#endregion Header
35
36using System;
37using System.Collections;
38using System.Collections.Generic;
39using System.Diagnostics;
40using System.Threading;
41
42using OpenMetaverse;
43
44using OpenSim;
45using OpenSim.Framework;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Physics.Manager;
49
50using log4net;
51
52namespace OpenSim.Region.Environment.Modules.ContentManagement
53{
54 /// <summary>
55 /// The controller in a Model-View-Controller framework. This controller catches actions by the avatars, creates work packets, loops through these work packets in a separate thread,
56 /// then dictates to the model how the data should change and dictates to the view which data should be displayed. The main mechanism for interaction is through the simchat system.
57 /// </summary>
58 public class CMController
59 {
60 #region Static Fields
61
62 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
63
64 /// <value>
65 /// The queue that keeps track of which actions have happened. The MainLoop thread eats through this queue.
66 /// </value>
67 private static OpenSim.Framework.BlockingQueue<Work> m_WorkQueue = new OpenSim.Framework.BlockingQueue<Work>();
68
69 #endregion Static Fields
70
71 #region Fields
72
73 //bool init = false;
74 int m_channel = -1;
75
76 /// <value>
77 /// The estate module is used to identify which clients are estateManagers. Presently, the controller only pays attention to estate managers.
78 /// </value>
79 IEstateModule m_estateModule = null;
80
81 //These have to be global variables, threading doesn't allow for passing parameters. (Used in MainLoop)
82 CMModel m_model = null;
83
84 /// <value>
85 /// A list of all the scenes that should be revisioned. Controller is the only class that keeps track of all scenes in the region.
86 /// </value>
87 Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable());
88 State m_state = State.NONE;
89 Thread m_thread = null;
90 CMView m_view = null;
91
92 #endregion Fields
93
94 #region Constructors
95
96 /// <summary>
97 /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method.
98 /// </summary>
99 /// <param name="model">
100 /// <see cref="CMModel"/>
101 /// </param>
102 /// <param name="view">
103 /// <see cref="CMView"/>
104 /// </param>
105 /// <param name="scene">
106 /// The first scene to keep track of. <see cref="Scene"/>
107 /// </param>
108 /// <param name="channel">
109 /// The simchat channel number to listen to for instructions <see cref="System.Int32"/>
110 /// </param>
111 public CMController(CMModel model, CMView view, Scene scene, int channel)
112 {
113 m_model = model; m_view = view; m_channel = channel;
114 RegisterNewRegion(scene);
115 Initialize(model, view, scene, channel);
116 }
117
118 #endregion Constructors
119
120 #region Private Methods
121
122 //------------------------------------------------ EVENTS ----------------------------------------------------//
123// private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID)
124// {
125// }
126
127 /// <summary>
128 /// Searches in all scenes for a SceneObjectGroup that contains a part with a specific localID. If found, the object is returned. Else null is returned.
129 /// </summary>
130 private SceneObjectGroup GetGroupByPrim(uint localID)
131 {
132 foreach (Object currScene in m_sceneList.Values)
133 {
134 foreach (EntityBase ent in ((Scene)currScene).GetEntities())
135 {
136 if (ent is SceneObjectGroup)
137 {
138 if (((SceneObjectGroup)ent).HasChildPrim(localID))
139 return (SceneObjectGroup)ent;
140 }
141 }
142 }
143 return null;
144 }
145
146 private void Initialize(CMModel model, CMView view, Scene scene, int channel)
147 {
148 lock (this)
149 {
150 m_estateModule = scene.RequestModuleInterface<IEstateModule>();
151 m_thread = new Thread(MainLoop);
152 m_thread.Name = "Content Management";
153 m_thread.IsBackground = true;
154 m_thread.Start();
155 ThreadTracker.Add(m_thread);
156 m_state = State.NONE;
157 }
158 }
159
160 /// <summary>
161 /// Run in a thread of its own. A endless loop that consumes (or blocks on) and work queue. Thw work queue is filled through client actions.
162 /// </summary>
163 private void MainLoop()
164 {
165 try
166 {
167 CMModel model = m_model; CMView view = m_view; int channel = m_channel;
168 Work currentJob = new Work();
169 while (true)
170 {
171 currentJob = m_WorkQueue.Dequeue();
172 m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request");
173 m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type);
174 switch (currentJob.Type)
175 {
176 case WorkType.NONE:
177 break;
178 case WorkType.OBJECTATTRIBUTECHANGE:
179 ObjectAttributeChanged(model, view, currentJob.LocalId);
180 break;
181 case WorkType.PRIMITIVEADDED:
182 PrimitiveAdded(model, view, currentJob);
183 break;
184 case WorkType.OBJECTDUPLICATED:
185 ObjectDuplicated(model, view, currentJob.LocalId);
186 break;
187 case WorkType.OBJECTKILLED:
188 ObjectKilled(model, view, (SceneObjectGroup) currentJob.Data1);
189 break;
190 case WorkType.UNDODID:
191 UndoDid(model, view, currentJob.UUID);
192 break;
193 case WorkType.NEWCLIENT:
194 NewClient(view, (IClientAPI) currentJob.Data1);
195 break;
196 case WorkType.SIMCHAT:
197 m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((OSChatMessage) currentJob.Data1).Message);
198 SimChat(model, view, (OSChatMessage) currentJob.Data1, channel);
199 break;
200 default:
201 m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?");
202 break;
203 }
204 }
205 }
206 catch (Exception e)
207 {
208 // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened
209 m_log.ErrorFormat(
210 "[CONTENT MANAGEMENT]: Content management thread terminating with exception. PLEASE REBOOT YOUR SIM - CONTENT MANAGEMENT WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}",
211 e);
212 }
213 }
214
215 /// <summary>
216 /// Only called by the MainLoop. Updates the view of a new client with metaentities if diff-mode is currently enabled.
217 /// </summary>
218 private void NewClient(CMView view, IClientAPI client)
219 {
220 if ((m_state & State.SHOWING_CHANGES) > 0)
221 view.SendMetaEntitiesToNewClient(client);
222 }
223
224 /// <summary>
225 /// Only called by the MainLoop.
226 /// </summary>
227 private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId)
228 {
229 SceneObjectGroup group = null;
230 if ((m_state & State.SHOWING_CHANGES) > 0)
231 {
232 group = GetGroupByPrim(LocalId);
233 if (group != null)
234 {
235 view.DisplayAuras(model.UpdateNormalEntityEffects(group)); //Might be a normal entity (green aura)
236 m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura)
237 }
238 }
239 }
240
241 /// <summary>
242 /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied.
243 /// </summary>
244 private void ObjectDuplicated(CMModel model, CMView view, uint localId)
245 {
246 if ((m_state & State.SHOWING_CHANGES) > 0)
247 view.DisplayAuras(model.CheckForNewEntitiesMissingAuras(GetGroupByPrim(localId).Scene));
248 }
249
250 /// <summary>
251 /// Only called by the MainLoop.
252 /// </summary>
253 private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group)
254 {
255 if ((m_state & State.SHOWING_CHANGES) > 0)
256 {
257 view.RemoveOrUpdateDeletedEntity(group);
258 model.RemoveOrUpdateDeletedEntity(group);
259 }
260 }
261
262 /// <summary>
263 /// Only called by the MainLoop.
264 /// </summary>
265 private void PrimitiveAdded(CMModel model, CMView view, Work currentJob)
266 {
267 if ((m_state & State.SHOWING_CHANGES) > 0)
268 {
269 foreach (Object scene in m_sceneList.Values)
270 m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene));
271 }
272 }
273
274 /// <summary>
275 /// Only called by the MainLoop.
276 /// </summary>
277 private void UndoDid(CMModel model, CMView view, UUID uuid)
278 {
279 if ((m_state & State.SHOWING_CHANGES) > 0)
280 {
281 ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid);
282 if (ent != null)
283 view.DisplayEntity(ent);
284 }
285 }
286
287 #endregion Private Methods
288
289 #region Protected Methods
290
291 protected void GroupBeingDeleted(SceneObjectGroup group)
292 {
293 m_log.Debug("[CONTENT MANAGEMENT] Something was deleted!!!");
294 Work moreWork = new Work();
295 moreWork.Type = WorkType.OBJECTKILLED;
296 moreWork.Data1 = group.Copy();
297 m_WorkQueue.Enqueue(moreWork);
298 }
299
300 protected void ObjectDuplicated(uint localID, Vector3 offset, uint dupeFlags, UUID AgentID, UUID GroupID)
301 {
302 Work moreWork = new Work();
303 moreWork.Type = WorkType.OBJECTDUPLICATED;
304 moreWork.LocalId = localID;
305 m_WorkQueue.Enqueue(moreWork);
306 m_log.Debug("[CONTENT MANAGEMENT] dup queue");
307 }
308
309 protected void ObjectDuplicatedOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID,
310 UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart,
311 bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates)
312 {
313 Work moreWork = new Work();
314 moreWork.Type = WorkType.OBJECTDUPLICATED;
315 moreWork.LocalId = localID;
316 m_WorkQueue.Enqueue(moreWork);
317 m_log.Debug("[CONTENT MANAGEMENT] dup queue");
318 }
319
320 protected void OnNewClient(IClientAPI client)
321 {
322 Work moreWork = new Work();
323 moreWork.Type = WorkType.NEWCLIENT;
324 moreWork.Data1 = client;
325 m_WorkQueue.Enqueue(moreWork);
326 m_log.Debug("[CONTENT MANAGEMENT] new client");
327 }
328
329 protected void OnUnDid(IClientAPI remoteClient, UUID primId)
330 {
331 Work moreWork = new Work();
332 moreWork.Type = WorkType.UNDODID;
333 moreWork.UUID = primId;
334 m_WorkQueue.Enqueue(moreWork);
335 m_log.Debug("[CONTENT MANAGEMENT] undid");
336 }
337
338 /// <summary>
339 /// Takes a list of scenes and forms a new orderd list according to the proximity of scenes to the second argument.
340 /// </summary>
341 protected static System.Collections.Generic.List<Scene> ScenesInOrderOfProximity(Hashtable sceneList, Scene scene)
342 {
343 int somethingAddedToList = 1;
344 System.Collections.Generic.List<Scene> newList = new List<Scene>();
345 newList.Add(scene);
346
347 if (!sceneList.ContainsValue(scene))
348 {
349 foreach (Object sceneObj in sceneList)
350 newList.Add((Scene) sceneObj);
351 return newList;
352 }
353
354 while (somethingAddedToList > 0)
355 {
356 somethingAddedToList = 0;
357 for (int i = 0; i < newList.Count; i++)
358 {
359 foreach (Object sceneObj in sceneList.Values)
360 {
361 if (newList[i].CheckNeighborRegion(((Scene)sceneObj).RegionInfo) && (!newList.Contains((Scene)sceneObj)))
362 {
363 newList.Add((Scene)sceneObj);
364 somethingAddedToList++;
365 }
366 }
367 }
368 }
369
370 foreach (Object sceneObj in sceneList.Values)
371 if (!newList.Contains((Scene)sceneObj))
372 newList.Add((Scene)sceneObj);
373
374 return newList;
375 }
376
377 //This is stupid, the same information is contained in the first and second argument
378 protected void SimChatSent(Object x, OSChatMessage e)
379 {
380 m_log.Debug("[CONTENT MANAGEMENT] SIMCHAT SENT !!!!!!!");
381 m_log.Debug("[CONTENT MANAGEMENT] message was: " + e.Message);
382 Work moreWork = new Work();
383 moreWork.Type = WorkType.SIMCHAT;
384 moreWork.Data1 = e;
385 m_WorkQueue.Enqueue(moreWork);
386 }
387
388 /// <summary>
389 /// Adds extra handlers to a number of events so that the controller can produce work based on the client's actions.
390 /// </summary>
391 protected void StartManaging(IClientAPI client)
392 {
393 m_log.Debug("[CONTENT MANAGEMENT] Registering channel with chat services.");
394 // client.OnChatFromClient += SimChatSent;
395 //init = true;
396
397 OnNewClient(client);
398
399 m_log.Debug("[CONTENT MANAGEMENT] Adding handlers to client.");
400 client.OnUpdatePrimScale += UpdateSingleScale;
401 client.OnUpdatePrimGroupScale += UpdateMultipleScale;
402 client.OnUpdatePrimGroupPosition += UpdateMultiplePosition;
403 client.OnUpdatePrimSinglePosition += UpdateSinglePosition;
404 client.OnUpdatePrimGroupRotation += UpdateMultipleRotation;
405 client.OnUpdatePrimSingleRotation += UpdateSingleRotation;
406 client.OnAddPrim += UpdateNewParts;
407 client.OnObjectDuplicate += ObjectDuplicated;
408 client.OnObjectDuplicateOnRay += ObjectDuplicatedOnRay;
409 client.OnUndo += OnUnDid;
410 //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation;
411 }
412
413 /// <summary>
414 ///
415 /// </summary>
416 protected void StopManaging(UUID clientUUID)
417 {
418 foreach (Object sceneobj in m_sceneList.Values)
419 {
420 ScenePresence presence = ((Scene)sceneobj).GetScenePresence(clientUUID);
421 if (presence != null)
422 {
423 IClientAPI client = presence.ControllingClient;
424 m_log.Debug("[CONTENT MANAGEMENT] Unregistering channel with chat services.");
425 // client.OnChatFromViewer -= SimChatSent;
426
427 m_log.Debug("[CONTENT MANAGEMENT] Removing handlers to client");
428 client.OnUpdatePrimScale -= UpdateSingleScale;
429 client.OnUpdatePrimGroupScale -= UpdateMultipleScale;
430 client.OnUpdatePrimGroupPosition -= UpdateMultiplePosition;
431 client.OnUpdatePrimSinglePosition -= UpdateSinglePosition;
432 client.OnUpdatePrimGroupRotation -= UpdateMultipleRotation;
433 client.OnUpdatePrimSingleRotation -= UpdateSingleRotation;
434 client.OnAddPrim -= UpdateNewParts;
435 client.OnObjectDuplicate -= ObjectDuplicated;
436 client.OnObjectDuplicateOnRay -= ObjectDuplicatedOnRay;
437 client.OnUndo -= OnUnDid;
438 //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation;
439 return;
440 }
441 }
442 }
443
444 protected void UpdateMultiplePosition(uint localID, Vector3 pos, IClientAPI remoteClient)
445 {
446 Work moreWork = new Work();
447 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
448 moreWork.LocalId = localID;
449 m_WorkQueue.Enqueue(moreWork);
450 m_log.Debug("[CONTENT MANAGEMENT] pos");
451 }
452
453 protected void UpdateMultipleRotation(uint localID, Quaternion rot, IClientAPI remoteClient)
454 {
455 Work moreWork = new Work();
456 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
457 moreWork.LocalId = localID;
458 m_WorkQueue.Enqueue(moreWork);
459 m_log.Debug("[CONTENT MANAGEMENT] rot");
460 }
461
462 protected void UpdateMultipleScale(uint localID, Vector3 scale, IClientAPI remoteClient)
463 {
464 Work moreWork = new Work();
465 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
466 moreWork.LocalId = localID;
467 m_WorkQueue.Enqueue(moreWork);
468 m_log.Debug("[CONTENT MANAGEMENT]scale");
469 }
470
471 protected void UpdateNewParts(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape,
472 byte bypassRaycast, Vector3 RayStart, UUID RayTargetID,
473 byte RayEndIsIntersection)
474 {
475 Work moreWork = new Work();
476 moreWork.Type = WorkType.PRIMITIVEADDED;
477 moreWork.UUID = ownerID;
478 m_WorkQueue.Enqueue(moreWork);
479 m_log.Debug("[CONTENT MANAGEMENT] new parts");
480 }
481
482 protected void UpdateSinglePosition(uint localID, Vector3 pos, IClientAPI remoteClient)
483 {
484 Work moreWork = new Work();
485 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
486 moreWork.LocalId = localID;
487 m_WorkQueue.Enqueue(moreWork);
488 m_log.Debug("[CONTENT MANAGEMENT] move");
489 }
490
491 /// <summary>
492 ///
493 /// </summary>
494 protected void UpdateSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient)
495 {
496 Work moreWork = new Work();
497 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
498 moreWork.LocalId = localID;
499 m_WorkQueue.Enqueue(moreWork);
500 m_log.Debug("[CONTENT MANAGEMENT] rot");
501 }
502
503 protected void UpdateSingleScale(uint localID, Vector3 scale, IClientAPI remoteClient)
504 {
505 Work moreWork = new Work();
506 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
507 moreWork.LocalId = localID;
508 m_WorkQueue.Enqueue(moreWork);
509 m_log.Debug("[CONTENT MANAGEMENT] scale");
510 }
511
512 /// <summary>
513 /// Only called from within the SimChat method.
514 /// </summary>
515 protected void commit(string message, Scene scene, CMModel model, CMView view)
516 {
517 System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene);
518
519 string[] args = message.Split(new char[] {' '});
520
521 char[] logMessage = {' '};
522 if (args.Length > 1)
523 {
524 logMessage = new char[message.Length - (args[0].Length)];
525 message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length));
526 }
527
528 m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region.");
529 foreach (Scene currScene in proximitySceneList)
530 {
531 model.CommitRegion(currScene, new String(logMessage));
532 view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName);
533 }
534
535 view.SendSimChatMessage(scene, "Successfully saved all regions.");
536 m_state |= State.DIRTY;
537
538 if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES
539 {
540 view.SendSimChatMessage(scene, "Updating differences between new revision and current environment.");
541 //Hide objects from users and Forget about them
542 view.HideAllMetaEntities();
543 view.HideAllAuras();
544 model.DeleteAllMetaObjects();
545
546 //Recreate them from backend files
547 foreach (Scene currScene in proximitySceneList)
548 {
549 model.UpdateCMEntities(currScene);
550 view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName);
551 }
552
553 //Display new objects to users1
554 view.DisplayRecentChanges();
555 view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE.");
556 m_state &= ~(State.DIRTY);
557 m_state |= State.SHOWING_CHANGES;
558 }
559 }
560
561 /// <summary>
562 /// Only called from within the SimChat method.
563 /// </summary>
564 protected void diffmode(Scene scene, CMModel model, CMView view)
565 {
566 System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene);
567
568 if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF
569 {
570 view.SendSimChatMessage(scene, "Hiding all meta objects.");
571 view.HideAllMetaEntities();
572 view.HideAllAuras();
573 view.SendSimChatMessage(scene, "Diff-mode = OFF");
574
575 m_state &= ~State.SHOWING_CHANGES;
576 return;
577 }
578 else // TURN ON
579 {
580 if ((m_state & State.DIRTY) != 0 || m_state == State.NONE)
581 {
582 view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision");
583 //Hide objects from users and Forget about them
584 view.HideAllMetaEntities();
585 view.HideAllAuras();
586 model.DeleteAllMetaObjects();
587 //Recreate them from backend files
588 foreach (Object currScene in m_sceneList.Values)
589 model.UpdateCMEntities((Scene) currScene);
590 }
591 else if ((m_state & State.DIRTY) != 0) {
592 view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision");
593 foreach (Scene currScene in proximitySceneList)
594 model.UpdateCMEntities(currScene);
595 }
596
597 view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment");
598 foreach (Scene currScene in proximitySceneList)
599 model.CheckForNewEntitiesMissingAuras(currScene);
600 view.DisplayRecentChanges();
601
602 view.SendSimChatMessage(scene, "Diff-mode = ON");
603 m_state |= State.SHOWING_CHANGES;
604 m_state &= ~State.DIRTY;
605 }
606 }
607
608 /// <summary>
609 /// Only called from within the SimChat method. Hides all auras and meta entities,
610 /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene,
611 /// then lets the view update the clients of the new objects.
612 /// </summary>
613 protected void rollback(Scene scene, CMModel model, CMView view)
614 {
615 if ((m_state & State.SHOWING_CHANGES) > 0)
616 {
617 view.HideAllAuras();
618 view.HideAllMetaEntities();
619 }
620
621 System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene);
622 foreach (Scene currScene in proximitySceneList)
623 model.RollbackRegion(currScene);
624
625 if ((m_state & State.DIRTY) != 0)
626 {
627 model.DeleteAllMetaObjects();
628 foreach (Scene currScene in proximitySceneList)
629 model.UpdateCMEntities(currScene);
630 }
631
632 if ((m_state & State.SHOWING_CHANGES) > 0)
633 view.DisplayRecentChanges();
634 }
635
636 #endregion Protected Methods
637
638 #region Public Methods
639
640 /// <summary>
641 /// Register a new scene object to keep track of for revisioning. Starts the controller monitoring actions of clients within the given scene.
642 /// </summary>
643 /// <param name="scene">
644 /// A <see cref="Scene"/>
645 /// </param>
646 public void RegisterNewRegion(Scene scene)
647 {
648 m_sceneList.Add(scene.RegionInfo.RegionID, scene);
649
650 m_log.Debug("[CONTENT MANAGEMENT] Registering new region: " + scene.RegionInfo.RegionID);
651 m_log.Debug("[CONTENT MANAGEMENT] Initializing Content Management System.");
652
653 scene.EventManager.OnNewClient += StartManaging;
654 scene.EventManager.OnChatFromClient += SimChatSent;
655 scene.EventManager.OnRemovePresence += StopManaging;
656 // scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
657 scene.EventManager.OnObjectBeingRemovedFromScene += GroupBeingDeleted;
658 }
659
660 /// <summary>
661 /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command.
662 /// </summary>
663 public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel)
664 {
665 if (e.Channel != channel)
666 return;
667 if (e.Sender == null)
668 return;
669
670 m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message);
671
672 IClientAPI client = e.Sender;
673 Scene scene = (Scene) e.Scene;
674 string message = e.Message;
675 string[] args = e.Message.Split(new char[] {' '});
676
677 ScenePresence avatar = scene.GetScenePresence(client.AgentId);
678
679 if (!(m_estateModule.IsManager(avatar.UUID)))
680 {
681 m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring.");
682 view.SendSimChatMessage(scene, "You must be an estate manager to perform that action.");
683 return;
684 }
685
686 switch (args[0])
687 {
688 case "ci":
689 case "commit":
690 commit(message, scene, model, view);
691 break;
692 case "dm":
693 case "diff-mode":
694 diffmode(scene, model, view);
695 break;
696 case "rb":
697 case "rollback":
698 rollback(scene, model, view);
699 break;
700 case "help":
701 m_view.DisplayHelpMenu(scene);
702 break;
703 default:
704 view.SendSimChatMessage(scene, "Command not found: " + args[0]);
705 break;
706 }
707 }
708
709 #endregion Public Methods
710
711 #region Other
712
713 /// <value>
714 /// Used to keep track of whether a list has been produced yet and whether that list is up-to-date compard to latest revision on disk.
715 /// </value>
716 [Flags]
717 private enum State
718 {
719 NONE = 0,
720 DIRTY = 1, // The meta entities may not correctly represent the last revision.
721 SHOWING_CHANGES = 1<<1 // The meta entities are being shown to user.
722 }
723
724 /// <value>
725 /// The structure that defines the basic unit of work which is produced when a user sends commands to the ContentMangaementSystem.
726 /// </value>
727 private struct Work
728 {
729 #region Fields
730
731 public Object Data1; //Just space for holding data.
732 public Object Data2; //Just more space for holding data.
733 public uint LocalId; //Convenient
734 public WorkType Type;
735 public UUID UUID; //Convenient
736
737 #endregion Fields
738 }
739
740 /// <value>
741 /// Identifies what the data in struct Work should be used for.
742 /// </value>
743 private enum WorkType
744 {
745 NONE,
746 OBJECTATTRIBUTECHANGE,
747 PRIMITIVEADDED,
748 OBJECTDUPLICATED,
749 OBJECTKILLED,
750 UNDODID,
751 NEWCLIENT,
752 SIMCHAT
753 }
754
755 #endregion Other
756 }
757}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs
deleted file mode 100644
index cfd5cde..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs
+++ /dev/null
@@ -1,193 +0,0 @@
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 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 */
27
28#region Header
29
30// CMEntityCollection.cs created with MonoDevelop
31// User: bongiojp at 10:09 AM 7/7/2008
32//
33// Creates, Deletes, Stores ContentManagementEntities
34//
35
36#endregion Header
37
38using System;
39using System.Collections;
40using System.Collections.Generic;
41using System.Threading;
42
43using OpenMetaverse;
44
45using Nini.Config;
46
47using OpenSim;
48using OpenSim.Framework;
49using OpenSim.Region.Framework.Interfaces;
50using OpenSim.Region.Framework.Scenes;
51using OpenSim.Region.Physics.Manager;
52
53using log4net;
54
55namespace OpenSim.Region.Environment.Modules.ContentManagement
56{
57 public class CMEntityCollection
58 {
59 #region Fields
60
61 // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
62 // Any ContentManagementEntities that represent old versions of current SceneObjectGroups or
63 // old versions of deleted SceneObjectGroups will be stored in this hash table.
64 // The UUID keys are from the SceneObjectGroup RootPart UUIDs
65 protected Hashtable m_CMEntityHash = Hashtable.Synchronized(new Hashtable()); //UUID to ContentManagementEntity
66
67 // SceneObjectParts that have not been revisioned will be given green auras stored in this hashtable
68 // The UUID keys are from the SceneObjectPart that they are supposed to be on.
69 protected Hashtable m_NewlyCreatedEntityAura = Hashtable.Synchronized(new Hashtable()); //UUID to AuraMetaEntity
70
71 #endregion Fields
72
73 #region Constructors
74
75 public CMEntityCollection()
76 {
77 }
78
79 #endregion Constructors
80
81 #region Public Properties
82
83 public Hashtable Auras
84 {
85 get {return m_NewlyCreatedEntityAura; }
86 }
87
88 public Hashtable Entities
89 {
90 get { return m_CMEntityHash; }
91 }
92
93 #endregion Public Properties
94
95 #region Public Methods
96
97 public bool AddAura(ContentManagementEntity aura)
98 {
99 if (m_NewlyCreatedEntityAura.ContainsKey(aura.UUID))
100 return false;
101 m_NewlyCreatedEntityAura.Add(aura.UUID, aura);
102 return true;
103 }
104
105 public bool AddEntity(ContentManagementEntity ent)
106 {
107 if (m_CMEntityHash.ContainsKey(ent.UUID))
108 return false;
109 m_CMEntityHash.Add(ent.UUID, ent);
110 return true;
111 }
112
113 // Check if there are SceneObjectGroups in the list that do not have corresponding ContentManagementGroups in the CMEntityHash
114 public System.Collections.ArrayList CheckForMissingEntities(System.Collections.Generic.List<EntityBase> currList)
115 {
116 System.Collections.ArrayList missingList = new System.Collections.ArrayList();
117 SceneObjectGroup temp = null;
118 foreach (EntityBase currObj in currList)
119 {
120 if (!(currObj is SceneObjectGroup))
121 continue;
122 temp = (SceneObjectGroup) currObj;
123
124 if (m_CMEntityHash.ContainsKey(temp.UUID))
125 {
126 foreach (SceneObjectPart part in temp.Children.Values)
127 if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID))
128 missingList.Add(part);
129 }
130 else //Entire group is missing from revision. (and is a new part in region)
131 {
132 foreach (SceneObjectPart part in temp.Children.Values)
133 missingList.Add(part);
134 }
135 }
136 return missingList;
137 }
138
139 public void ClearAll()
140 {
141 m_CMEntityHash.Clear();
142 m_NewlyCreatedEntityAura.Clear();
143 }
144
145 // Old uuid and new sceneobjectgroup
146 public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part)
147 {
148 AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene,
149 part.GetWorldPosition(),
150 MetaEntity.TRANSLUCENT,
151 new Vector3(0,254,0),
152 part.Scale
153 );
154 m_NewlyCreatedEntityAura.Add(part.UUID, ent);
155 return ent;
156 }
157
158 // Old uuid and new sceneobjectgroup
159 public ContentManagementEntity CreateNewEntity(SceneObjectGroup group)
160 {
161 ContentManagementEntity ent = new ContentManagementEntity(group, false);
162 m_CMEntityHash.Add(group.UUID, ent);
163 return ent;
164 }
165
166 public ContentManagementEntity CreateNewEntity(String xml, Scene scene)
167 {
168 ContentManagementEntity ent = new ContentManagementEntity(xml, scene, false);
169 if (ent == null)
170 return null;
171 m_CMEntityHash.Add(ent.UnchangedEntity.UUID, ent);
172 return ent;
173 }
174
175 public bool RemoveEntity(UUID uuid)
176 {
177 if (!m_CMEntityHash.ContainsKey(uuid))
178 return false;
179 m_CMEntityHash.Remove(uuid);
180 return true;
181 }
182
183 public bool RemoveNewlyCreatedEntityAura(UUID uuid)
184 {
185 if (!m_NewlyCreatedEntityAura.ContainsKey(uuid))
186 return false;
187 m_NewlyCreatedEntityAura.Remove(uuid);
188 return true;
189 }
190
191 #endregion Public Methods
192 }
193}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs
deleted file mode 100644
index 6399608..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs
+++ /dev/null
@@ -1,362 +0,0 @@
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 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 */
27
28#region Header
29
30// CMModel.cs
31// User: bongiojp
32//
33//
34
35#endregion Header
36
37using System;
38using System.Collections;
39using System.Collections.Generic;
40using System.Diagnostics;
41
42using OpenMetaverse;
43
44using OpenSim;
45using OpenSim.Framework;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Physics.Manager;
49
50using log4net;
51
52namespace OpenSim.Region.Environment.Modules.ContentManagement
53{
54 public class CMModel
55 {
56 #region Static Fields
57
58 static float TimeToUpdate = 0;
59 static float TimeToConvertXml = 0;
60 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
61
62 #endregion Static Fields
63
64 #region Fields
65
66 /// <value>
67 /// The class that contains all auras and metaentities used in the CMS.
68 /// </value>
69 CMEntityCollection m_MetaEntityCollection = new CMEntityCollection();
70 IContentDatabase m_database = null;
71
72 #endregion Fields
73
74 #region Constructors
75
76 public CMModel()
77 {
78 }
79
80 #endregion Constructors
81
82 #region Public Properties
83
84 public CMEntityCollection MetaEntityCollection
85 {
86 get { return m_MetaEntityCollection; }
87 }
88
89 #endregion Public Properties
90
91 #region Public Methods
92
93 /// <summary>
94 /// Compares the scene's object group list to the list of meta entities. If there is an object group that does not have a corresponding meta entity
95 /// it is a new part that must have a green aura (for diff mode).
96 /// Returns list of ContentManagementEntities
97 /// </summary>
98 public ArrayList CheckForNewEntitiesMissingAuras(Scene scene)
99 {
100 ArrayList missingList = null;
101 ArrayList newList = new ArrayList();
102
103 m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName);
104
105 //Check if the current scene has groups not included in the current list of MetaEntities
106 //If so, then the current scene's parts that are new should be marked green.
107 missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities());
108
109 foreach (Object missingPart in missingList)
110 {
111 if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID))
112 continue;
113 newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart));
114 }
115 m_log.Info("Number of missing objects found: " + newList.Count);
116 return newList;
117 }
118
119 /// <summary>
120 /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message.
121 /// </summary>
122 public void CommitRegion(Scene scene, String logMessage)
123 {
124 m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length);
125 m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage);
126 m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName );
127 }
128
129 public void DeleteAllMetaObjects()
130 {
131 m_MetaEntityCollection.ClearAll();
132 }
133
134 public ContentManagementEntity FindMetaEntityAffectedByUndo(UUID uuid)
135 {
136 ContentManagementEntity ent = GetMetaGroupByPrim(uuid);
137 return ent;
138 }
139
140 //-------------------------------- HELPERS --------------------------------------------------------------------//
141 public ContentManagementEntity GetMetaGroupByPrim(UUID uuid)
142 {
143 foreach (Object ent in m_MetaEntityCollection.Entities.Values)
144 {
145 if (((ContentManagementEntity)ent).HasChildPrim(uuid))
146 return (ContentManagementEntity)ent;
147 }
148 return null;
149 }
150
151 public void Initialise(string database)
152 {
153 if (database == "FileSystemDatabase")
154 m_database = new FileSystemDatabase();
155 else if (database == "GitDatabase")
156 m_database = new GitDatabase();
157 }
158
159 public void InitialiseDatabase(Scene scene, string dir)
160 {
161 m_database.Initialise(scene, dir);
162 }
163
164 /// <summary>
165 /// Should be called just once to finish initializing the database.
166 /// </summary>
167 public void PostInitialise()
168 {
169 m_database.PostInitialise();
170 }
171
172 /// <summary>
173 /// Removes the green aura when an a new scene object group is deleted.
174 /// </summary>
175 public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group)
176 {
177 // Deal with new parts not revisioned that have been deleted.
178 foreach (SceneObjectPart part in group.Children.Values)
179 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
180 m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID);
181 }
182
183 /// <summary>
184 /// Retrieves the latest revision of a region in xml form,
185 /// converts it to scene object groups and scene presences,
186 /// swaps the current scene's entity list with the revision's list.
187 /// Note: Since deleted objects while
188 /// </summary>
189 public void RollbackRegion(Scene scene)
190 {
191 System.Collections.ArrayList xmllist = null;
192 SceneObjectGroup temp = null;
193 System.Collections.Hashtable deleteListUUIDs = new Hashtable();
194// Dictionary<LLUUID, EntityBase> SearchList = new Dictionary<LLUUID,EntityBase>();
195 Dictionary<UUID, EntityBase> ReplacementList = new Dictionary<UUID,EntityBase>();
196 int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID);
197// EntityBase[] searchArray;
198
199 xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision);
200 if (xmllist == null)
201 {
202 m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ").");
203 return;
204 }
205
206 m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ").");
207 m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count);
208 m_log.Info("[CMMODEL]: Converting scene entities list to specified revision.");
209
210 m_log.ErrorFormat("[CMMODEL]: 1");
211
212 foreach (string xml in xmllist)
213 {
214 try{
215 temp = new SceneObjectGroup(xml);
216 temp.SetScene(scene);
217 foreach (SceneObjectPart part in temp.Children.Values)
218 part.RegionHandle = scene.RegionInfo.RegionHandle;
219 ReplacementList.Add(temp.UUID, (EntityBase)temp);
220 }
221 catch(Exception e)
222 {
223 m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e);
224 }
225 }
226
227 //If in scene but not in revision and not a client, remove them
228 while (true)
229 {
230 try
231 {
232 foreach (EntityBase entity in scene.GetEntities())
233 {
234 if (entity == null)
235 continue;
236
237 if (entity is ScenePresence)
238 {
239 ReplacementList.Add(entity.UUID, entity);
240 continue;
241 }
242 else //if (!ReplacementList.ContainsKey(entity.UUID))
243 deleteListUUIDs.Add(entity.UUID, 0);
244 }
245 }
246 catch(Exception e)
247 {
248 m_log.ErrorFormat("[CMMODEL]: " + e);
249 deleteListUUIDs.Clear();
250 ReplacementList.Clear();
251 continue;
252 }
253 break;
254 }
255
256 foreach (UUID uuid in deleteListUUIDs.Keys)
257 {
258 try
259 {
260 // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles.
261 ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup();
262 scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor);
263 scene.SendKillObject(scene.Entities[uuid].LocalId);
264 scene.m_sceneGraph.DeleteSceneObject(uuid, false);
265 ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroup(false);
266 }
267 catch(Exception e)
268 {
269 m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e);
270 }
271 }
272
273 lock (scene)
274 {
275 scene.Entities.Clear();
276
277 foreach (KeyValuePair<UUID,EntityBase> kvp in ReplacementList)
278 {
279 scene.Entities.Add(kvp.Value);
280 }
281 }
282
283 foreach (EntityBase ent in ReplacementList.Values)
284 {
285 try
286 {
287 if (!(ent is SceneObjectGroup))
288 continue;
289
290 if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) == 0)
291 ((SceneObjectGroup)ent).ApplyPhysics(true);
292 ((SceneObjectGroup)ent).AttachToBackup();
293 ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected.
294 ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate();
295 }
296 catch(Exception e)
297 {
298 m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e);
299 }
300 }
301 m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup.");
302 scene.Backup();
303 }
304
305 /// <summary>
306 /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences
307 /// and display the differences to clients.
308 /// </summary>
309 public void UpdateCMEntities(Scene scene)
310 {
311 Stopwatch x = new Stopwatch();
312 x.Start();
313
314 System.Collections.ArrayList xmllist = null;
315 m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID);
316 xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID);
317 m_log.Info("[FSDB]: got list");
318 if (xmllist == null)
319 return;
320
321 Stopwatch y = new Stopwatch();
322 y.Start();
323 foreach (string xml in xmllist)
324 m_MetaEntityCollection.CreateNewEntity(xml, scene);
325 y.Stop();
326 TimeToConvertXml += y.ElapsedMilliseconds;
327 m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds);
328 m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml);
329
330 m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras");
331 CheckForNewEntitiesMissingAuras(scene);
332
333 x.Stop();
334 TimeToUpdate += x.ElapsedMilliseconds;
335 m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds);
336 m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate);
337 }
338
339 /// <summary>
340 /// Detects if a scene object group from the scene list has moved or changed scale. The green aura
341 /// that surrounds the object is then moved or scaled with the group.
342 /// </summary>
343 public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group)
344 {
345 System.Collections.ArrayList auraList = new System.Collections.ArrayList();
346 if (group == null)
347 return null;
348 foreach (SceneObjectPart part in group.Children.Values)
349 {
350 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
351 {
352 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale);
353 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
354 auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
355 }
356 }
357 return auraList;
358 }
359
360 #endregion Public Methods
361 }
362}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs
deleted file mode 100644
index e5c9bb3..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs
+++ /dev/null
@@ -1,206 +0,0 @@
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 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 */
27
28#region Header
29
30// CMView.cs created with MonoDevelop
31// User: bongiojp at 11:57 AM 7/3/2008
32//
33// To change standard headers go to Edit->Preferences->Coding->Standard Headers
34//
35
36#endregion Header
37
38using System;
39using System.Collections;
40using System.Collections.Generic;
41
42using OpenMetaverse;
43
44using OpenSim;
45using OpenSim.Framework;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Physics.Manager;
49
50using log4net;
51
52namespace OpenSim.Region.Environment.Modules.ContentManagement
53{
54 public class CMView
55 {
56 #region Static Fields
57
58 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
59
60 #endregion Static Fields
61
62 #region Fields
63
64 CMModel m_model = null;
65
66 #endregion Fields
67
68 #region Constructors
69
70 public CMView()
71 {
72 }
73
74 #endregion Constructors
75
76 #region Public Methods
77
78 // Auras To
79 public void DisplayAuras(CMEntityCollection auraCollection)
80 {
81 foreach (Object ent in auraCollection.Auras.Values)
82 ((AuraMetaEntity)ent).SendFullUpdateToAll();
83 }
84
85 // Auras To Client
86 public void DisplayAuras(CMEntityCollection auraCollection, IClientAPI client)
87 {
88 foreach (Object ent in auraCollection.Auras.Values)
89 ((AuraMetaEntity)ent).SendFullUpdate(client);
90 }
91
92 // Auras from List To ALL
93 public void DisplayAuras(ArrayList list)
94 {
95 foreach (Object ent in list)
96 {
97 m_log.Debug("[CONTENT MANAGEMENT] displaying new aura riiiiiiiiiiiight NOW");
98 ((AuraMetaEntity)ent).SendFullUpdateToAll();
99 }
100 }
101
102 // Entities to ALL
103 public void DisplayEntities(CMEntityCollection entityCollection)
104 {
105 foreach (Object ent in entityCollection.Entities.Values)
106 ((ContentManagementEntity)ent).SendFullDiffUpdateToAll();
107 }
108
109 // Entities to Client
110 public void DisplayEntities(CMEntityCollection entityCollection, IClientAPI client)
111 {
112 foreach (Object ent in entityCollection.Entities.Values)
113 ((ContentManagementEntity)ent).SendFullDiffUpdate(client);
114 }
115
116 // Entities from List to ALL
117 public void DisplayEntities(ArrayList list)
118 {
119 foreach (Object ent in list)
120 ((ContentManagementEntity)ent).SendFullDiffUpdateToAll();
121 }
122
123 // Entity to ALL
124 public void DisplayEntity(ContentManagementEntity ent)
125 {
126 ent.SendFullDiffUpdateToAll();
127 }
128
129 public void DisplayHelpMenu(Scene scene)
130 {
131 string menu = "Menu:\n";
132 menu += "commit (ci) - saves current state of the region to a database on the server\n";
133 menu += "diff-mode (dm) - displays those aspects of region that have not been saved but changed since the very last revision. Will dynamically update as you change environment.\n";
134 SendSimChatMessage(scene, menu);
135 }
136
137 public void DisplayMetaEntity(UUID uuid)
138 {
139 ContentManagementEntity group = m_model.GetMetaGroupByPrim(uuid);
140 if (group != null)
141 group.SendFullDiffUpdateToAll();
142 }
143
144 /// <summary>
145 /// update all clients of red/green/blue auras and meta entities that the model knows about.
146 /// </summary>
147 public void DisplayRecentChanges()
148 {
149 m_log.Debug("[CONTENT MANAGEMENT] Sending update to clients for " + m_model.MetaEntityCollection.Entities.Count + " objects.");
150 DisplayEntities(m_model.MetaEntityCollection);
151 DisplayAuras(m_model.MetaEntityCollection);
152 }
153
154 public void Hide(ContentManagementEntity ent)
155 {
156 ent.HideFromAll();
157 }
158
159 public void HideAllAuras()
160 {
161 foreach (Object obj in m_model.MetaEntityCollection.Auras.Values)
162 ((MetaEntity)obj).HideFromAll();
163 }
164
165 public void HideAllMetaEntities()
166 {
167 foreach (Object obj in m_model.MetaEntityCollection.Entities.Values)
168 ((ContentManagementEntity)obj).HideFromAll();
169 }
170
171 public void Initialise(CMModel model)
172 {
173 m_model = model;
174 }
175
176 /// <summary>
177 /// Figures out if the part deleted was a new scene object part or a revisioned part that's been deleted.
178 /// If it's a new scene object, any green aura attached to it is deleted.
179 /// If a revisioned part is deleted, a new full update is sent to the environment of the meta entity, which will
180 /// figure out that there should be a red aura and not a blue aura/beam.
181 /// </summary>
182 public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group)
183 {
184 // Deal with revisioned parts that have been deleted.
185 if (m_model.MetaEntityCollection.Entities.ContainsKey(group.UUID))
186 ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll();
187
188 // Deal with new parts not revisioned that have been deleted.
189 foreach (SceneObjectPart part in group.Children.Values)
190 if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID))
191 ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll();
192 }
193
194 public void SendMetaEntitiesToNewClient(IClientAPI client)
195 {
196 }
197
198 public void SendSimChatMessage(Scene scene, string message)
199 {
200 scene.SimChat(Utils.StringToBytes(message),
201 ChatTypeEnum.Broadcast, 0, new Vector3(0,0,0), "Content Manager", UUID.Zero, false);
202 }
203
204 #endregion Public Methods
205 }
206}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs
deleted file mode 100644
index 2ea5ebc..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs
+++ /dev/null
@@ -1,383 +0,0 @@
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 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 */
27
28#region Header
29
30// ContentManagementEntity.cs
31// User: bongiojp
32//
33//
34
35#endregion Header
36
37using System;
38using System.Collections.Generic;
39using System.Drawing;
40
41using OpenMetaverse;
42
43using Nini.Config;
44
45using OpenSim.Framework;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Physics.Manager;
49
50using log4net;
51
52namespace OpenSim.Region.Environment.Modules.ContentManagement
53{
54 public class ContentManagementEntity : MetaEntity
55 {
56 #region Static Fields
57
58// static float TimeToDiff = 0;
59// static float TimeToCreateEntities = 0;
60
61 #endregion Static Fields
62
63 #region Fields
64
65 protected Dictionary<UUID, AuraMetaEntity> m_AuraEntities = new Dictionary<UUID, AuraMetaEntity>();
66 protected Dictionary<UUID, BeamMetaEntity> m_BeamEntities = new Dictionary<UUID, BeamMetaEntity>();
67
68 // The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different.
69 // This can come in handy.
70 protected SceneObjectGroup m_UnchangedEntity = null;
71
72 /// <value>
73 /// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list.
74 /// </value>
75 bool DiffersFromSceneGroup = false;
76
77 #endregion Fields
78
79 #region Constructors
80
81 public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics)
82 : base(Unchanged, false)
83 {
84 m_UnchangedEntity = Unchanged.Copy(Unchanged.RootPart.OwnerID, Unchanged.RootPart.GroupID, false);
85 }
86
87 public ContentManagementEntity(string objectXML, Scene scene, bool physics)
88 : base(objectXML, scene, false)
89 {
90 m_UnchangedEntity = new SceneObjectGroup(objectXML);
91 }
92
93 #endregion Constructors
94
95 #region Public Properties
96
97 public SceneObjectGroup UnchangedEntity
98 {
99 get { return m_UnchangedEntity; }
100 }
101
102 #endregion Public Properties
103
104 #region Private Methods
105
106 /// <summary>
107 /// Check if an entitybase list (like that returned by scene.GetEntities()) contains a group with the rootpart uuid that matches the current uuid.
108 /// </summary>
109 private bool ContainsKey(List<EntityBase> list, UUID uuid)
110 {
111 foreach (EntityBase part in list)
112 if (part.UUID == uuid)
113 return true;
114 return false;
115 }
116
117 private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List<EntityBase> list, UUID uuid)
118 {
119 foreach (EntityBase ent in list)
120 {
121 if (ent is SceneObjectGroup)
122 if (ent.UUID == uuid)
123 return (SceneObjectGroup)ent;
124 }
125 return null;
126 }
127
128 #endregion Private Methods
129
130 #region Public Methods
131
132 /// <summary>
133 /// Search for a corresponding group UUID in the scene. If not found, then the revisioned group this CMEntity represents has been deleted. Mark the metaentity appropriately.
134 /// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately.
135 /// </summary>
136 public void FindDifferences()
137 {
138 System.Collections.Generic.List<EntityBase> sceneEntityList = m_Entity.Scene.GetEntities();
139 DiffersFromSceneGroup = false;
140 // if group is not contained in scene's list
141 if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID))
142 {
143 foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
144 {
145 // if scene list no longer contains this part, display translucent part and mark with red aura
146 if (!ContainsKey(sceneEntityList, part.UUID))
147 {
148 // if already displaying a red aura over part, make sure its red
149 if (m_AuraEntities.ContainsKey(part.UUID))
150 {
151 m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale);
152 }
153 else
154 {
155 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
156 part.GetWorldPosition(),
157 MetaEntity.TRANSLUCENT,
158 new Vector3(254,0,0),
159 part.Scale
160 );
161 m_AuraEntities.Add(part.UUID, auraGroup);
162 }
163 SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum);
164 SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT);
165 }
166 // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id
167 }
168
169 // a deleted part has no where to point a beam particle system,
170 // if a metapart had a particle system (maybe it represented a moved part) remove it
171 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
172 {
173 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
174 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
175 }
176
177 DiffersFromSceneGroup = true;
178 }
179 // if scene list does contain group, compare each part in group for differences and display beams and auras appropriately
180 else
181 {
182 MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID));
183 }
184 }
185
186 /// <summary>
187 /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID.
188 /// </summary>
189 public bool HasChildPrim(UUID uuid)
190 {
191 if (m_UnchangedEntity.Children.ContainsKey(uuid))
192 return true;
193 return false;
194 }
195
196 /// <summary>
197 /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId.
198 /// </summary>
199 public bool HasChildPrim(uint localID)
200 {
201 foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
202 if (part.LocalId == localID)
203 return true;
204 return false;
205 }
206
207 public override void Hide(IClientAPI client)
208 {
209 base.Hide(client);
210 foreach (MetaEntity group in m_AuraEntities.Values)
211 group.Hide(client);
212 foreach (MetaEntity group in m_BeamEntities.Values)
213 group.Hide(client);
214 }
215
216 public override void HideFromAll()
217 {
218 base.HideFromAll();
219 foreach (MetaEntity group in m_AuraEntities.Values)
220 group.HideFromAll();
221 foreach (MetaEntity group in m_BeamEntities.Values)
222 group.HideFromAll();
223 }
224
225 /// <summary>
226 /// Returns true if there was a change between meta entity and the entity group, false otherwise.
227 /// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated).
228 /// </summary>
229 public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup)
230 {
231 SceneObjectPart sceneEntityPart;
232 SceneObjectPart metaEntityPart;
233 Diff differences;
234 bool changed = false;
235
236 // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user
237 // had originally saved.
238 // m_Entity will NOT necessarily be the same entity as the user had saved.
239 foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values)
240 {
241 //This is the part that we use to show changes.
242 metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum);
243 if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID))
244 {
245 sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID];
246 differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart);
247 if (differences != Diff.NONE)
248 metaEntityPart.Text = "CHANGE: " + differences.ToString();
249 if (differences != 0)
250 {
251 // Root Part that has been modified
252 if ((differences&Diff.POSITION) > 0)
253 {
254 // If the position of any part has changed, make sure the RootPart of the
255 // meta entity is pointing with a beam particle system
256 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
257 {
258 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
259 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
260 }
261 BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene,
262 m_UnchangedEntity.RootPart.GetWorldPosition(),
263 MetaEntity.TRANSLUCENT,
264 sceneEntityPart,
265 new Vector3(0,0,254)
266 );
267 m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup);
268 }
269
270 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
271 {
272 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
273 m_AuraEntities.Remove(UnchangedPart.UUID);
274 }
275 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
276 UnchangedPart.GetWorldPosition(),
277 MetaEntity.TRANSLUCENT,
278 new Vector3(0,0,254),
279 UnchangedPart.Scale
280 );
281 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
282 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
283
284 DiffersFromSceneGroup = true;
285 }
286 else // no differences between scene part and meta part
287 {
288 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
289 {
290 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
291 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
292 }
293 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
294 {
295 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
296 m_AuraEntities.Remove(UnchangedPart.UUID);
297 }
298 SetPartTransparency(metaEntityPart, MetaEntity.NONE);
299 }
300 }
301 else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
302 {
303 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
304 {
305 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
306 m_AuraEntities.Remove(UnchangedPart.UUID);
307 }
308 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
309 UnchangedPart.GetWorldPosition(),
310 MetaEntity.TRANSLUCENT,
311 new Vector3(254,0,0),
312 UnchangedPart.Scale
313 );
314 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
315 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
316
317 DiffersFromSceneGroup = true;
318 }
319 }
320 return changed;
321 }
322
323 public void SendFullAuraUpdate(IClientAPI client)
324 {
325 if (DiffersFromSceneGroup)
326 {
327 foreach (AuraMetaEntity group in m_AuraEntities.Values)
328 group.SendFullUpdate(client);
329 }
330 }
331
332 public void SendFullAuraUpdateToAll()
333 {
334 if (DiffersFromSceneGroup)
335 {
336 foreach (AuraMetaEntity group in m_AuraEntities.Values)
337 group.SendFullUpdateToAll();
338 }
339 }
340
341 public void SendFullBeamUpdate(IClientAPI client)
342 {
343 if (DiffersFromSceneGroup)
344 {
345 foreach (BeamMetaEntity group in m_BeamEntities.Values)
346 group.SendFullUpdate(client);
347 }
348 }
349
350 public void SendFullBeamUpdateToAll()
351 {
352 if (DiffersFromSceneGroup)
353 {
354 foreach (BeamMetaEntity group in m_BeamEntities.Values)
355 group.SendFullUpdateToAll();
356 }
357 }
358
359 public void SendFullDiffUpdate(IClientAPI client)
360 {
361 FindDifferences();
362 if (DiffersFromSceneGroup)
363 {
364 SendFullUpdate(client);
365 SendFullAuraUpdate(client);
366 SendFullBeamUpdate(client);
367 }
368 }
369
370 public void SendFullDiffUpdateToAll()
371 {
372 FindDifferences();
373 if (DiffersFromSceneGroup)
374 {
375 SendFullUpdateToAll();
376 SendFullAuraUpdateToAll();
377 SendFullBeamUpdateToAll();
378 }
379 }
380
381 #endregion Public Methods
382 }
383}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs
deleted file mode 100644
index 417cbce..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs
+++ /dev/null
@@ -1,163 +0,0 @@
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 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 */
27
28#region Header
29
30// ContentManagementModule.cs
31// User: bongiojp
32
33#endregion Header
34
35using System;
36using System.Collections.Generic;
37using System.Threading;
38
39using OpenMetaverse;
40
41using Nini.Config;
42
43using OpenSim;
44using OpenSim.Framework;
45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Physics.Manager;
48
49using log4net;
50
51namespace OpenSim.Region.Environment.Modules.ContentManagement
52{
53 public class ContentManagementModule : IRegionModule
54 {
55 #region Static Fields
56
57 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
58
59 #endregion Static Fields
60
61 #region Fields
62
63 bool initialised = false;
64 CMController m_control = null;
65 bool m_enabled = false;
66 CMModel m_model = null;
67 bool m_posted = false;
68 CMView m_view = null;
69
70 #endregion Fields
71
72 #region Public Properties
73
74 public bool IsSharedModule
75 {
76 get { return true; }
77 }
78
79 public string Name
80 {
81 get { return "ContentManagementModule"; }
82 }
83
84 #endregion Public Properties
85
86 #region Public Methods
87
88 public void Close()
89 {
90 }
91
92 public void Initialise(Scene scene, IConfigSource source)
93 {
94 string databaseDir = "./";
95 string database = "FileSystemDatabase";
96 int channel = 345;
97 try
98 {
99 if (source.Configs["CMS"] == null)
100 return;
101
102 m_enabled = source.Configs["CMS"].GetBoolean("enabled", false);
103 databaseDir = source.Configs["CMS"].GetString("directory", databaseDir);
104 database = source.Configs["CMS"].GetString("database", database);
105 channel = source.Configs["CMS"].GetInt("channel", channel);
106
107 if (database != "FileSystemDatabase" && database != "GitDatabase")
108 {
109 m_log.ErrorFormat("[Content Management]: The Database attribute must be defined as either FileSystemDatabase or GitDatabase");
110 m_enabled = false;
111 }
112 }
113 catch (Exception e)
114 {
115 m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e);
116 m_enabled = false;
117 }
118
119 if (!m_enabled)
120 {
121 m_log.Info("[Content Management]: Content Management System is not Enabled.");
122 return;
123 }
124
125 lock (this)
126 {
127 if (!initialised) //only init once
128 {
129 m_view = new CMView();
130 m_model = new CMModel();
131 m_control = new CMController(m_model, m_view, scene, channel);
132 m_model.Initialise(database);
133 m_view.Initialise(m_model);
134
135 initialised = true;
136 m_model.InitialiseDatabase(scene, databaseDir);
137 }
138 else
139 {
140 m_model.InitialiseDatabase(scene, databaseDir);
141 m_control.RegisterNewRegion(scene);
142 }
143 }
144 }
145
146 public void PostInitialise()
147 {
148 if (! m_enabled)
149 return;
150
151 lock (this)
152 {
153 if (!m_posted) //only post once
154 {
155 m_model.PostInitialise();
156 m_posted = true;
157 }
158 }
159 }
160
161 #endregion Public Methods
162 }
163}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs
deleted file mode 100644
index 65db153..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs
+++ /dev/null
@@ -1,317 +0,0 @@
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 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 */
27
28#region Header
29
30// FileSystemDatabase.cs
31// User: bongiojp
32
33#endregion Header
34
35using System;
36using System.Collections.Generic;
37using System.Diagnostics;
38using System.IO;
39using Slash = System.IO.Path;
40using System.Reflection;
41using System.Xml;
42
43using OpenMetaverse;
44
45using Nini.Config;
46
47using OpenSim.Framework;
48using OpenSim.Region.Framework.Interfaces;
49using OpenSim.Region.Framework.Scenes;
50using OpenSim.Region.Environment.Modules.World.Serialiser;
51using OpenSim.Region.Environment.Modules.World.Terrain;
52using OpenSim.Region.Physics.Manager;
53
54using log4net;
55
56namespace OpenSim.Region.Environment.Modules.ContentManagement
57{
58 public class FileSystemDatabase : IContentDatabase
59 {
60 #region Static Fields
61
62 public static float TimeToDownload = 0;
63 public static float TimeToSave = 0;
64 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
65
66 #endregion Static Fields
67
68 #region Fields
69
70 private string m_repodir = null;
71 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
72 private Dictionary<UUID, IRegionSerialiserModule> m_serialiser = new Dictionary<UUID, IRegionSerialiserModule>();
73
74 #endregion Fields
75
76 #region Constructors
77
78 public FileSystemDatabase()
79 {
80 }
81
82 #endregion Constructors
83
84 #region Private Methods
85
86 // called by postinitialise
87 private void CreateDirectory()
88 {
89 string scenedir;
90 if (!Directory.Exists(m_repodir))
91 Directory.CreateDirectory(m_repodir);
92
93 foreach (UUID region in m_scenes.Keys)
94 {
95 scenedir = m_repodir + Slash.DirectorySeparatorChar + region + Slash.DirectorySeparatorChar;
96 if (!Directory.Exists(scenedir))
97 Directory.CreateDirectory(scenedir);
98 }
99 }
100
101 // called by postinitialise
102 private void SetupSerialiser()
103 {
104 if (m_serialiser.Count == 0)
105 {
106 foreach (UUID region in m_scenes.Keys)
107 {
108 m_serialiser.Add(region, m_scenes[region].RequestModuleInterface<IRegionSerialiserModule>());
109 }
110 }
111 }
112
113 #endregion Private Methods
114
115 #region Public Methods
116
117 public int GetMostRecentRevision(UUID regionid)
118 {
119 return NumOfRegionRev(regionid);
120 }
121
122 public string GetRegionObjectHeightMap(UUID regionid)
123 {
124 String filename = m_repodir + Slash.DirectorySeparatorChar + regionid +
125 Slash.DirectorySeparatorChar + "heightmap.r32";
126 FileStream fs = new FileStream( filename, FileMode.Open);
127 StreamReader sr = new StreamReader(fs);
128 String result = sr.ReadToEnd();
129 sr.Close();
130 fs.Close();
131 return result;
132 }
133
134 public string GetRegionObjectHeightMap(UUID regionid, int revision)
135 {
136 String filename = m_repodir + Slash.DirectorySeparatorChar + regionid +
137 Slash.DirectorySeparatorChar + "heightmap.r32";
138 FileStream fs = new FileStream( filename, FileMode.Open);
139 StreamReader sr = new StreamReader(fs);
140 String result = sr.ReadToEnd();
141 sr.Close();
142 fs.Close();
143 return result;
144 }
145
146 public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision)
147 {
148 System.Collections.ArrayList objectList = new System.Collections.ArrayList();
149 string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar +
150 + revision + Slash.DirectorySeparatorChar + "objects.xml";
151 XmlDocument doc = new XmlDocument();
152 XmlNode rootNode;
153 //int primCount = 0;
154 //SceneObjectGroup obj = null;
155
156 if (File.Exists(filename))
157 {
158 XmlTextReader reader = new XmlTextReader(filename);
159 reader.WhitespaceHandling = WhitespaceHandling.None;
160 doc.Load(reader);
161 reader.Close();
162 rootNode = doc.FirstChild;
163 foreach (XmlNode aPrimNode in rootNode.ChildNodes)
164 {
165 objectList.Add(aPrimNode.OuterXml);
166 }
167 return objectList;
168 }
169 return null;
170 }
171
172 public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid)
173 {
174 int revision = NumOfRegionRev(regionid);
175 m_log.Info("[FSDB]: found revisions:" + revision);
176 System.Collections.ArrayList xmlList = new System.Collections.ArrayList();
177 string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar +
178 + revision + Slash.DirectorySeparatorChar + "objects.xml";
179 XmlDocument doc = new XmlDocument();
180 XmlNode rootNode;
181
182 m_log.Info("[FSDB]: Checking if " + filename + " exists.");
183 if (File.Exists(filename))
184 {
185 Stopwatch x = new Stopwatch();
186 x.Start();
187
188 XmlTextReader reader = new XmlTextReader(filename);
189 reader.WhitespaceHandling = WhitespaceHandling.None;
190 doc.Load(reader);
191 reader.Close();
192 rootNode = doc.FirstChild;
193
194 foreach (XmlNode aPrimNode in rootNode.ChildNodes)
195 {
196 xmlList.Add(aPrimNode.OuterXml);
197 }
198
199 x.Stop();
200 TimeToDownload += x.ElapsedMilliseconds;
201 m_log.Info("[FileSystemDatabase] Time spent retrieving xml files so far: " + TimeToDownload);
202
203 return xmlList;
204 }
205 return null;
206 }
207
208 public void Initialise(Scene scene, string dir)
209 {
210 lock (this)
211 {
212 if (m_repodir == null)
213 m_repodir = dir;
214 }
215 lock (m_scenes)
216 m_scenes.Add(scene.RegionInfo.RegionID, scene);
217 }
218
219 public System.Collections.Generic.SortedDictionary<string, string> ListOfRegionRevisions(UUID regionid)
220 {
221 SortedDictionary<string, string> revisionDict = new SortedDictionary<string,string>();
222
223 string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar;
224 string[] directories = Directory.GetDirectories(scenedir);
225
226 FileStream fs = null;
227 StreamReader sr = null;
228 String logMessage = "";
229 String logLocation = "";
230 foreach (string revisionDir in directories)
231 {
232 try
233 {
234 logLocation = revisionDir + Slash.DirectorySeparatorChar + "log";
235 fs = new FileStream( logLocation, FileMode.Open);
236 sr = new StreamReader(fs);
237 logMessage = sr.ReadToEnd();
238 sr.Close();
239 fs.Close();
240 revisionDict.Add(revisionDir, logMessage);
241 }
242 catch (Exception)
243 {
244 }
245 }
246
247 return revisionDict;
248 }
249
250 public int NumOfRegionRev(UUID regionid)
251 {
252 string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar;
253 m_log.Info("[FSDB]: Reading scene dir: " + scenedir);
254 string[] directories = Directory.GetDirectories(scenedir);
255 return directories.Length;
256 }
257
258 // Run once and only once.
259 public void PostInitialise()
260 {
261 SetupSerialiser();
262
263 m_log.Info("[FSDB]: Creating repository in " + m_repodir + ".");
264 CreateDirectory();
265 }
266
267 public void SaveRegion(UUID regionid, string regionName, string logMessage)
268 {
269 m_log.Info("[FSDB]: ...............................");
270 string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar;
271
272 m_log.Info("[FSDB]: checking if scene directory exists: " + scenedir);
273 if (!Directory.Exists(scenedir))
274 Directory.CreateDirectory(scenedir);
275
276 int newRevisionNum = GetMostRecentRevision(regionid)+1;
277 string revisiondir = scenedir + newRevisionNum + Slash.DirectorySeparatorChar;
278
279 m_log.Info("[FSDB]: checking if revision directory exists: " + revisiondir);
280 if (!Directory.Exists(revisiondir))
281 Directory.CreateDirectory(revisiondir);
282
283 try {
284 Stopwatch x = new Stopwatch();
285 x.Start();
286 if (m_scenes.ContainsKey(regionid))
287 {
288 m_serialiser[regionid].SerialiseRegion(m_scenes[regionid], revisiondir);
289 }
290 x.Stop();
291 TimeToSave += x.ElapsedMilliseconds;
292 m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk for " + regionName + ": " + x.ElapsedMilliseconds);
293 m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk so far: " + TimeToSave);
294 }
295 catch (Exception e)
296 {
297 m_log.ErrorFormat("[FSDB]: Serialisation of region failed: " + e);
298 return;
299 }
300
301 try {
302 // Finish by writing log message.
303 FileStream file = new FileStream(revisiondir + "log", FileMode.Create, FileAccess.ReadWrite);
304 StreamWriter sw = new StreamWriter(file);
305 sw.Write(logMessage);
306 sw.Close();
307 }
308 catch (Exception e)
309 {
310 m_log.ErrorFormat("[FSDB]: Failed trying to save log file " + e);
311 return;
312 }
313 }
314
315 #endregion Public Methods
316 }
317}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs
deleted file mode 100644
index 4209dab..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs
+++ /dev/null
@@ -1,167 +0,0 @@
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 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 */
27
28#region Header
29
30// GitDatabase.cs
31//
32//
33//
34
35#endregion Header
36
37using System;
38using System.Collections.Generic;
39using System.IO;
40using Slash = System.IO.Path;
41using System.Reflection;
42using System.Xml;
43
44using OpenMetaverse;
45
46using Nini.Config;
47
48using OpenSim.Framework;
49using OpenSim.Region.Framework.Interfaces;
50using OpenSim.Region.Framework.Scenes;
51using OpenSim.Region.Environment.Modules.World.Serialiser;
52using OpenSim.Region.Environment.Modules.World.Terrain;
53using OpenSim.Region.Physics.Manager;
54
55using log4net;
56
57namespace OpenSim.Region.Environment.Modules.ContentManagement
58{
59 /// <summary>
60 /// Just a stub :-(
61 /// </summary>
62 public class GitDatabase : IContentDatabase
63 {
64 #region Constructors
65
66 public GitDatabase()
67 {
68 }
69
70 #endregion Constructors
71
72 #region Public Methods
73
74 public SceneObjectGroup GetMostRecentObjectRevision(UUID id)
75 {
76 return null;
77 }
78
79 public int GetMostRecentRevision(UUID regionid)
80 {
81 return 0;
82 }
83
84 public SceneObjectGroup GetObjectRevision(UUID id, int revision)
85 {
86 return null;
87 }
88
89 public System.Collections.ArrayList GetObjectsFromRegion(UUID regionid, int revision)
90 {
91 return null;
92 }
93
94 public string GetRegionObjectHeightMap(UUID regionid)
95 {
96 return null;
97 }
98
99 public string GetRegionObjectHeightMap(UUID regionid, int revision)
100 {
101 return null;
102 }
103
104 public string GetRegionObjectXML(UUID regionid)
105 {
106 return null;
107 }
108
109 public string GetRegionObjectXML(UUID regionid, int revision)
110 {
111 return null;
112 }
113
114 public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid)
115 {
116 return null;
117 }
118
119 public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision)
120 {
121 return null;
122 }
123
124 public bool InRepository(UUID id)
125 {
126 return false;
127 }
128
129 public void Initialise(Scene scene, String dir)
130 {
131 }
132
133 public System.Collections.Generic.SortedDictionary<string, string> ListOfObjectRevisions(UUID id)
134 {
135 return null;
136 }
137
138 public System.Collections.Generic.SortedDictionary<string, string> ListOfRegionRevisions(UUID id)
139 {
140 return null;
141 }
142
143 public int NumOfObjectRev(UUID id)
144 {
145 return 0;
146 }
147
148 public int NumOfRegionRev(UUID regionid)
149 {
150 return 0;
151 }
152
153 public void PostInitialise()
154 {
155 }
156
157 public void SaveObject(SceneObjectGroup entity)
158 {
159 }
160
161 public void SaveRegion(UUID regionid, string regionName, string logMessage)
162 {
163 }
164
165 #endregion Public Methods
166 }
167}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs
deleted file mode 100644
index 79dc86e..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs
+++ /dev/null
@@ -1,94 +0,0 @@
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 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 */
27
28#region Header
29
30// IContentDatabase.cs
31// User: bongiojp
32//
33//
34//
35
36#endregion Header
37
38using System;
39using OpenMetaverse;
40using OpenSim.Region.Framework.Scenes;
41using Nini.Config;
42
43namespace OpenSim.Region.Environment.Modules.ContentManagement
44{
45 public interface IContentDatabase
46 {
47 #region Methods
48
49 /// <summary>
50 /// Returns the most recent revision number of a region.
51 /// </summary>
52 int GetMostRecentRevision(UUID regionid);
53
54 string GetRegionObjectHeightMap(UUID regionid);
55
56 string GetRegionObjectHeightMap(UUID regionid, int revision);
57
58 /// <summary>
59 /// Retrieves the xml that describes each individual object from the last revision or specific revision of the given region.
60 /// </summary>
61 System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid);
62
63 System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision);
64
65 /// <summary>
66 /// Similar to the IRegionModule function. This is the function to be called before attempting to interface with the database.
67 /// Initialise should be called one for each region to be contained in the database. The directory should be the full path
68 /// to the repository and will only be defined once, regardless of how many times the method is called.
69 /// </summary>
70 void Initialise(Scene scene, String dir);
71
72 /// <summary>
73 /// Returns a list of the revision numbers and corresponding log messages for a given region.
74 /// </summary>
75 System.Collections.Generic.SortedDictionary<string, string> ListOfRegionRevisions(UUID id);
76
77 /// <summary>
78 /// Returns the total number of revisions saved for a specific region.
79 /// </summary>
80 int NumOfRegionRev(UUID regionid);
81
82 /// <summary>
83 /// Should be called once after Initialise has been called.
84 /// </summary>
85 void PostInitialise();
86
87 /// <summary>
88 /// Saves the Region terrain map and objects within the region as xml to the database.
89 /// </summary>
90 void SaveRegion(UUID regionid, string regionName, string logMessage);
91
92 #endregion Methods
93 }
94}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs
deleted file mode 100644
index c8f8c2f..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs
+++ /dev/null
@@ -1,274 +0,0 @@
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 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 */
27
28#region Header
29
30// MetaEntity.cs
31// User: bongiojp
32//
33// TODO:
34// Create a physics manager to the meta object if there isn't one or the object knows of no scene but the user wants physics enabled.
35
36#endregion Header
37
38using System;
39using System.Collections.Generic;
40using System.Drawing;
41
42using OpenMetaverse;
43
44using Nini.Config;
45
46using OpenSim.Framework;
47using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Physics.Manager;
50
51using log4net;
52
53namespace OpenSim.Region.Environment.Modules.ContentManagement
54{
55 public class MetaEntity
56 {
57 #region Constants
58
59 public const float INVISIBLE = .95f;
60
61 // Settings for transparency of metaentity
62 public const float NONE = 0f;
63 public const float TRANSLUCENT = .5f;
64
65 #endregion Constants
66
67 #region Static Fields
68
69 protected static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
70
71 #endregion Static Fields
72
73 #region Fields
74
75 protected SceneObjectGroup m_Entity = null; // The scene object group that represents this meta entity.
76 protected uint m_metaLocalid;
77
78 #endregion Fields
79
80 #region Constructors
81
82 public MetaEntity()
83 {
84 }
85
86 /// <summary>
87 /// Makes a new meta entity by copying the given scene object group.
88 /// The physics boolean is just a stub right now.
89 /// </summary>
90 public MetaEntity(SceneObjectGroup orig, bool physics)
91 {
92 m_Entity = orig.Copy(orig.RootPart.OwnerID, orig.RootPart.GroupID, false);
93 Initialize(physics);
94 }
95
96 /// <summary>
97 /// Takes an XML description of a scene object group and converts it to a meta entity.
98 /// </summary>
99 public MetaEntity(string objectXML, Scene scene, bool physics)
100 {
101 m_Entity = new SceneObjectGroup(objectXML);
102 m_Entity.SetScene(scene);
103 Initialize(physics);
104 }
105
106 #endregion Constructors
107
108 #region Public Properties
109
110 public Dictionary<UUID, SceneObjectPart> Children
111 {
112 get { return m_Entity.Children; }
113 set { m_Entity.Children = value; }
114 }
115
116 public uint LocalId
117 {
118 get { return m_Entity.LocalId; }
119 set { m_Entity.LocalId = value; }
120 }
121
122 public SceneObjectGroup ObjectGroup
123 {
124 get { return m_Entity; }
125 }
126
127 public int PrimCount
128 {
129 get { return m_Entity.PrimCount; }
130 }
131
132 public SceneObjectPart RootPart
133 {
134 get { return m_Entity.RootPart; }
135 }
136
137 public Scene Scene
138 {
139 get { return m_Entity.Scene; }
140 }
141
142 public UUID UUID
143 {
144 get { return m_Entity.UUID; }
145 set { m_Entity.UUID = value; }
146 }
147
148 #endregion Public Properties
149
150 #region Protected Methods
151
152 // The metaentity objectgroup must have unique localids as well as unique uuids.
153 // localids are used by the client to refer to parts.
154 // uuids are sent to the client and back to the server to identify parts on the server side.
155 /// <summary>
156 /// Changes localids and uuids of m_Entity.
157 /// </summary>
158 protected void Initialize(bool physics)
159 {
160 //make new uuids
161 Dictionary<UUID, SceneObjectPart> parts = new Dictionary<UUID, SceneObjectPart>();
162 foreach (SceneObjectPart part in m_Entity.Children.Values)
163 {
164 part.ResetIDs(part.LinkNum);
165 parts.Add(part.UUID, part);
166 }
167
168 //finalize
169 m_Entity.RootPart.PhysActor = null;
170 m_Entity.Children = parts;
171 }
172
173 #endregion Protected Methods
174
175 #region Public Methods
176
177 /// <summary>
178 /// Hides the metaentity from a single client.
179 /// </summary>
180 public virtual void Hide(IClientAPI client)
181 {
182 //This deletes the group without removing from any databases.
183 //This is important because we are not IN any database.
184 //m_Entity.FakeDeleteGroup();
185 foreach (SceneObjectPart part in m_Entity.Children.Values)
186 client.SendKillObject(m_Entity.RegionHandle, part.LocalId);
187 }
188
189 /// <summary>
190 /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server.
191 /// </summary>
192 public virtual void HideFromAll()
193 {
194 foreach (SceneObjectPart part in m_Entity.Children.Values)
195 m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller)
196 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
197 );
198 }
199
200 public void SendFullUpdate(IClientAPI client)
201 {
202 // Not sure what clientFlags should be but 0 seems to work
203 SendFullUpdate(client, 0);
204 }
205
206 public void SendFullUpdate(IClientAPI client, uint clientFlags)
207 {
208 m_Entity.SendFullUpdateToClient(client);
209 }
210
211 public void SendFullUpdateToAll()
212 {
213 m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller)
214 { m_Entity.SendFullUpdateToClient(controller); }
215 );
216 }
217
218 /// <summary>
219 /// Makes a single SceneObjectPart see through.
220 /// </summary>
221 /// <param name="part">
222 /// A <see cref="SceneObjectPart"/>
223 /// The part to make see through
224 /// </param>
225 /// <param name="transparencyAmount">
226 /// A <see cref="System.Single"/>
227 /// The degree of transparency to imbue the part with, 0f being solid and .95f being invisible.
228 /// </param>
229 public static void SetPartTransparency(SceneObjectPart part, float transparencyAmount)
230 {
231 Primitive.TextureEntry tex = null;
232 Color4 texcolor;
233 try
234 {
235 tex = part.Shape.Textures;
236 texcolor = new Color4();
237 }
238 catch(Exception)
239 {
240 //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing textures of scene object: " + e);
241 return;
242 }
243
244 for (uint i = 0; i < tex.FaceTextures.Length; i++)
245 {
246 try {
247 if (tex.FaceTextures[i] != null)
248 {
249 texcolor = tex.FaceTextures[i].RGBA;
250 texcolor.A = transparencyAmount;
251 tex.FaceTextures[i].RGBA = texcolor;
252 }
253 }
254 catch (Exception)
255 {
256 //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing different face textures of object: " + e);
257 continue;
258 }
259 }
260 try {
261 texcolor = tex.DefaultTexture.RGBA;
262 texcolor.A = transparencyAmount;
263 tex.DefaultTexture.RGBA = texcolor;
264 part.Shape.TextureEntry = tex.ToBytes();
265 }
266 catch (Exception)
267 {
268 //m_log.Info("[Content Management]: Exception thrown while accessing default face texture of object: " + e);
269 }
270 }
271
272 #endregion Public Methods
273 }
274}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs
deleted file mode 100644
index d6ba92f..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs
+++ /dev/null
@@ -1,116 +0,0 @@
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 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 */
27
28#region Header
29
30// PointMetaEntity.cs created with MonoDevelop
31// User: bongiojp at 3:03 PM 8/6/2008
32//
33// To change standard headers go to Edit->Preferences->Coding->Standard Headers
34//
35
36#endregion Header
37
38using System;
39using System.Collections.Generic;
40using System.Drawing;
41
42using OpenMetaverse;
43
44using Nini.Config;
45
46using OpenSim.Framework;
47using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Physics.Manager;
50
51using log4net;
52
53namespace OpenSim.Region.Environment.Modules.ContentManagement
54{
55 public class PointMetaEntity : MetaEntity
56 {
57 #region Constructors
58
59 public PointMetaEntity(Scene scene, Vector3 groupPos, float transparency)
60 : base()
61 {
62 CreatePointEntity(scene, UUID.Random(), groupPos);
63 SetPartTransparency(m_Entity.RootPart, transparency);
64 }
65
66 public PointMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency)
67 : base()
68 {
69 CreatePointEntity(scene, uuid, groupPos);
70 SetPartTransparency(m_Entity.RootPart, transparency);
71 }
72
73 #endregion Constructors
74
75 #region Private Methods
76
77 private void CreatePointEntity(Scene scene, UUID uuid, Vector3 groupPos)
78 {
79 SceneObjectGroup x = new SceneObjectGroup();
80 SceneObjectPart y = new SceneObjectPart();
81
82 //Initialize part
83 y.Name = "Very Small Point";
84 y.RegionHandle = scene.RegionInfo.RegionHandle;
85 y.CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
86 y.OwnerID = UUID.Zero;
87 y.CreatorID = UUID.Zero;
88 y.LastOwnerID = UUID.Zero;
89 y.UUID = uuid;
90
91 y.Shape = PrimitiveBaseShape.CreateBox();
92 y.Scale = new Vector3(0.01f,0.01f,0.01f);
93 y.LastOwnerID = UUID.Zero;
94 y.GroupPosition = groupPos;
95 y.OffsetPosition = new Vector3(0, 0, 0);
96 y.RotationOffset = new Quaternion(0,0,0,0);
97 y.Velocity = new Vector3(0, 0, 0);
98 y.RotationalVelocity = new Vector3(0, 0, 0);
99 y.AngularVelocity = new Vector3(0, 0, 0);
100 y.Acceleration = new Vector3(0, 0, 0);
101
102 y.Flags = 0;
103 y.TrimPermissions();
104
105 //Initialize group and add part as root part
106 x.SetScene(scene);
107 x.SetRootPart(y);
108 x.RegionHandle = scene.RegionInfo.RegionHandle;
109 x.SetScene(scene);
110
111 m_Entity = x;
112 }
113
114 #endregion Private Methods
115 }
116}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/README b/OpenSim/Region/Environment/Modules/ContentManagementSystem/README
deleted file mode 100644
index 1a69fef..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/README
+++ /dev/null
@@ -1,52 +0,0 @@
1This module is meant to be built alone and not added to the Opensim code base. References are made to required dlls through a
2reference file, ContentManagement.mdp. Originally, for development, this project was contained in the Opensim/Region/Modules/
3directory.
4
5To compile: nant
6To use: Copy ContentManagement.dll into the bin directory of your Opensim build. You should find many other dlls in the same directory.
7
8
9--------------------------------------------------------------------------------------------------------------------
10To build the libgit.so file:
11
12#Download GIT git repository
13$ git clone git://git2.kernel.org/pub/OpenSim/Region/Environment/Modules/ContentManagementSystem/scm/git/git.git
14$ cd git
15
16#Compile GIT
17#Note that we are adding two extra flags to pass to gcc while compiling (-c and -fPIC)
18$ autoconf
19$ ./configure
20$ CFLAGS="-g -O2 -Wall -c -fPIC" make
21
22#Copy necessary object files (and some not so necessary) to their own directory for shared object file creation
23$ mkdir ../libgit-objects
24$ cp builtin*.o ../libgit-objects
25$ cp xdiff/*.o ../libgit-objects
26$ cp libgit.a ../libgit-objects
27
28#Remove the main symbol from any object files (like git.o)
29$ cd ../libgit-objects
30$ strip -N main *.o
31
32#Uncompress the plumbing objects from archive created by git
33$ ar x libgit.a
34
35#Create shared object file from all objects (including the zlib library)
36$ ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o
37
38
39#You can also just copy the following commands into a file and run as a script inside the git directory
40
41make clean
42autoconf
43./configure
44CFLAGS="-g -O2 -Wall -c -fPIC" make
45mkdir libgit-objects
46cp builtin*.o libgit-objects
47cp xdiff/*.o libgit-objects
48cp libgit.a libgit-objects
49cd libgit-objects
50strip -N main *.o
51ar x libgit.a
52ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs
deleted file mode 100644
index 225a682..0000000
--- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs
+++ /dev/null
@@ -1,218 +0,0 @@
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 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 */
27
28#region Header
29
30// SceneObjectGroupDiff.cs
31// User: bongiojp
32
33#endregion Header
34
35using System;
36using System.Collections.Generic;
37using System.Diagnostics;
38using System.Drawing;
39
40using OpenMetaverse;
41
42using Nini.Config;
43
44using OpenSim.Framework;
45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Physics.Manager;
48
49using log4net;
50
51namespace OpenSim.Region.Environment.Modules.ContentManagement
52{
53 #region Enumerations
54
55 [Flags]
56 public enum Diff
57 {
58 NONE = 0,
59 FACECOLOR = 1,
60 SHAPE = 1<<1,
61 MATERIAL = 1<<2,
62 TEXTURE = 1<<3,
63 SCALE = 1<<4,
64 POSITION = 1<<5,
65 OFFSETPOSITION = 1<<6,
66 ROTATIONOFFSET = 1<<7,
67 ROTATIONALVELOCITY = 1<<8,
68 ACCELERATION = 1<<9,
69 ANGULARVELOCITY = 1<<10,
70 VELOCITY = 1<<11,
71 OBJECTOWNER = 1<<12,
72 PERMISSIONS = 1<<13,
73 DESCRIPTION = 1<<14,
74 NAME = 1<<15,
75 SCRIPT = 1<<16,
76 CLICKACTION = 1<<17,
77 PARTICLESYSTEM = 1<<18,
78 GLOW = 1<<19,
79 SALEPRICE = 1<<20,
80 SITNAME = 1<<21,
81 SITTARGETORIENTATION = 1<<22,
82 SITTARGETPOSITION = 1<<23,
83 TEXT = 1<<24,
84 TOUCHNAME = 1<<25
85 }
86
87 #endregion Enumerations
88
89 public static class Difference
90 {
91 #region Static Fields
92
93 static float TimeToDiff = 0;
94// private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
95
96 #endregion Static Fields
97
98 #region Private Methods
99
100 private static bool AreQuaternionsEquivalent(Quaternion first, Quaternion second)
101 {
102 Vector3 firstVector = llRot2Euler(first);
103 Vector3 secondVector = llRot2Euler(second);
104 return AreVectorsEquivalent(firstVector, secondVector);
105 }
106
107 private static bool AreVectorsEquivalent(Vector3 first, Vector3 second)
108 {
109 if (TruncateSignificant(first.X, 2) == TruncateSignificant(second.X, 2)
110 && TruncateSignificant(first.Y, 2) == TruncateSignificant(second.Y, 2)
111 && TruncateSignificant(first.Z, 2) == TruncateSignificant(second.Z, 2)
112 )
113 return true;
114 else
115 return false;
116 }
117
118 // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
119 private static double NormalizeAngle(double angle)
120 {
121 angle = angle % (Math.PI * 2);
122 if (angle < 0) angle = angle + Math.PI * 2;
123 return angle;
124 }
125
126 private static int TruncateSignificant(float num, int digits)
127 {
128 return (int) Math.Ceiling((Math.Truncate(num * 10 * digits)/10*digits));
129 // return (int) ((num * (10*digits))/10*digits);
130 }
131
132 // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
133 // Also changed the original function from LSL_Types to LL types
134 private static Vector3 llRot2Euler(Quaternion r)
135 {
136 Quaternion t = new Quaternion(r.X * r.X, r.Y * r.Y, r.Z * r.Z, r.W * r.W);
137 double m = (t.X + t.Y + t.Z + t.W);
138 if (m == 0) return new Vector3();
139 double n = 2 * (r.Y * r.W + r.X * r.Z);
140 double p = m * m - n * n;
141 if (p > 0)
142 return new Vector3((float)NormalizeAngle(Math.Atan2(2.0 * (r.X * r.W - r.Y * r.Z), (-t.X - t.Y + t.Z + t.W))),
143 (float)NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))),
144 (float)NormalizeAngle(Math.Atan2(2.0 * (r.Z * r.W - r.X * r.Y), (t.X - t.Y - t.Z + t.W))));
145 else if (n > 0)
146 return new Vector3(0.0f, (float)(Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z)));
147 else
148 return new Vector3(0.0f, (float)(-Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z)));
149 }
150
151 #endregion Private Methods
152
153 #region Public Methods
154
155 /// <summary>
156 /// Compares the attributes (Vectors, Quaternions, Strings, etc.) between two scene object parts
157 /// and returns a Diff bitmask which details what the differences are.
158 /// </summary>
159 public static Diff FindDifferences(SceneObjectPart first, SceneObjectPart second)
160 {
161 Stopwatch x = new Stopwatch();
162 x.Start();
163
164 Diff result = 0;
165
166 // VECTOR COMPARISONS
167 if (!AreVectorsEquivalent(first.Acceleration, second.Acceleration))
168 result |= Diff.ACCELERATION;
169 if (!AreVectorsEquivalent(first.AbsolutePosition, second.AbsolutePosition))
170 result |= Diff.POSITION;
171 if (!AreVectorsEquivalent(first.AngularVelocity, second.AngularVelocity))
172 result |= Diff.ANGULARVELOCITY;
173 if (!AreVectorsEquivalent(first.OffsetPosition, second.OffsetPosition))
174 result |= Diff.OFFSETPOSITION;
175 if (!AreVectorsEquivalent(first.RotationalVelocity, second.RotationalVelocity))
176 result |= Diff.ROTATIONALVELOCITY;
177 if (!AreVectorsEquivalent(first.Scale, second.Scale))
178 result |= Diff.SCALE;
179 if (!AreVectorsEquivalent(first.Velocity, second.Velocity))
180 result |= Diff.VELOCITY;
181
182
183 // QUATERNION COMPARISONS
184 if (!AreQuaternionsEquivalent(first.RotationOffset, second.RotationOffset))
185 result |= Diff.ROTATIONOFFSET;
186
187
188 // MISC COMPARISONS (UUID, Byte)
189 if (first.ClickAction != second.ClickAction)
190 result |= Diff.CLICKACTION;
191 if (first.ObjectOwner != second.ObjectOwner)
192 result |= Diff.OBJECTOWNER;
193
194
195 // STRING COMPARISONS
196 if (first.Description != second.Description)
197 result |= Diff.DESCRIPTION;
198 if (first.Material != second.Material)
199 result |= Diff.MATERIAL;
200 if (first.Name != second.Name)
201 result |= Diff.NAME;
202 if (first.SitName != second.SitName)
203 result |= Diff.SITNAME;
204 if (first.Text != second.Text)
205 result |= Diff.TEXT;
206 if (first.TouchName != second.TouchName)
207 result |= Diff.TOUCHNAME;
208
209 x.Stop();
210 TimeToDiff += x.ElapsedMilliseconds;
211 //m_log.Info("[DIFFERENCES] Time spent diffing objects so far" + TimeToDiff);
212
213 return result;
214 }
215
216 #endregion Public Methods
217 }
218}
diff --git a/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueGetModule.cs
deleted file mode 100644
index fb30321..0000000
--- a/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueGetModule.cs
+++ /dev/null
@@ -1,630 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Net.Sockets;
33using System.Reflection;
34using System.Threading;
35using System.Xml;
36using OpenMetaverse;
37using OpenMetaverse.Packets;
38using OpenMetaverse.StructuredData;
39using log4net;
40using Nini.Config;
41using Nwc.XmlRpc;
42using OpenSim.Framework;
43using OpenSim.Framework.Communications.Cache;
44using OpenSim.Framework.Communications.Capabilities;
45using OpenSim.Framework.Servers;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes;
48
49using OSD = OpenMetaverse.StructuredData.OSD;
50using OSDMap = OpenMetaverse.StructuredData.OSDMap;
51using OSDArray = OpenMetaverse.StructuredData.OSDArray;
52using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
53using BlockingLLSDQueue = OpenSim.Framework.BlockingQueue<OpenMetaverse.StructuredData.OSD>;
54
55namespace OpenSim.Region.Environment.Modules.Framework.EventQueue
56{
57 public struct QueueItem
58 {
59 public int id;
60 public OSDMap body;
61 }
62
63 public class EventQueueGetModule : IEventQueue, IRegionModule
64 {
65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
66 private Scene m_scene = null;
67 private IConfigSource m_gConfig;
68 bool enabledYN = false;
69
70 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
71
72 private Dictionary<UUID, BlockingLLSDQueue> queues = new Dictionary<UUID, BlockingLLSDQueue>();
73 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>();
74 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
75
76 #region IRegionModule methods
77 public void Initialise(Scene scene, IConfigSource config)
78 {
79 m_gConfig = config;
80
81 IConfig startupConfig = m_gConfig.Configs["Startup"];
82
83 ReadConfigAndPopulate(scene, startupConfig, "Startup");
84
85 if (enabledYN)
86 {
87 m_scene = scene;
88 scene.RegisterModuleInterface<IEventQueue>(this);
89
90 // Register fallback handler
91 // Why does EQG Fail on region crossings!
92
93 //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack);
94
95 scene.EventManager.OnNewClient += OnNewClient;
96
97 // TODO: Leaving these open, or closing them when we
98 // become a child is incorrect. It messes up TP in a big
99 // way. CAPS/EQ need to be active as long as the UDP
100 // circuit is there.
101
102 scene.EventManager.OnClientClosed += ClientClosed;
103 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
104 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
105 }
106 else
107 {
108 m_gConfig = null;
109 }
110
111 }
112
113 private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p)
114 {
115 enabledYN = startupConfig.GetBoolean("EventQueue", true);
116 }
117
118 public void PostInitialise()
119 {
120 }
121
122 public void Close()
123 {
124 }
125
126 public string Name
127 {
128 get { return "EventQueueGetModule"; }
129 }
130
131 public bool IsSharedModule
132 {
133 get { return false; }
134 }
135 #endregion
136
137 /// <summary>
138 /// Always returns a valid queue
139 /// </summary>
140 /// <param name="agentId"></param>
141 /// <returns></returns>
142 private BlockingLLSDQueue TryGetQueue(UUID agentId)
143 {
144 lock (queues)
145 {
146 if (!queues.ContainsKey(agentId))
147 {
148 m_log.DebugFormat(
149 "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}",
150 agentId, m_scene.RegionInfo.RegionName);
151
152 queues[agentId] = new BlockingLLSDQueue();
153 }
154
155 return queues[agentId];
156 }
157 }
158
159 /// <summary>
160 /// May return a null queue
161 /// </summary>
162 /// <param name="agentId"></param>
163 /// <returns></returns>
164 private BlockingLLSDQueue GetQueue(UUID agentId)
165 {
166 lock (queues)
167 {
168 if (queues.ContainsKey(agentId))
169 {
170 return queues[agentId];
171 }
172 else
173 return null;
174 }
175 }
176
177 #region IEventQueue Members
178
179 public bool Enqueue(OSD ev, UUID avatarID)
180 {
181 //m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName);
182 try
183 {
184 BlockingLLSDQueue queue = GetQueue(avatarID);
185 if (queue != null)
186 queue.Enqueue(ev);
187 }
188 catch(NullReferenceException e)
189 {
190 m_log.Error("[EVENTQUEUE] Caught exception: " + e);
191 return false;
192 }
193
194 return true;
195 }
196
197 #endregion
198
199 private void OnNewClient(IClientAPI client)
200 {
201 //client.OnLogout += ClientClosed;
202 }
203
204// private void ClientClosed(IClientAPI client)
205// {
206// ClientClosed(client.AgentId);
207// }
208
209 private void ClientClosed(UUID AgentID)
210 {
211 m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName);
212
213 int count = 0;
214 while (queues.ContainsKey(AgentID) && queues[AgentID].Count() > 0 && count++ < 5)
215 {
216 Thread.Sleep(1000);
217 }
218
219 lock (queues)
220 {
221 queues.Remove(AgentID);
222 }
223 List<UUID> removeitems = new List<UUID>();
224 lock (m_AvatarQueueUUIDMapping)
225 {
226 foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
227 {
228 if (ky == AgentID)
229 {
230 removeitems.Add(ky);
231 }
232 }
233
234 foreach (UUID ky in removeitems)
235 {
236 m_AvatarQueueUUIDMapping.Remove(ky);
237 m_scene.CommsManager.HttpServer.RemoveHTTPHandler("","/CAPS/EQG/" + ky.ToString() + "/");
238 }
239
240 }
241 UUID searchval = UUID.Zero;
242
243 removeitems.Clear();
244
245 lock (m_QueueUUIDAvatarMapping)
246 {
247 foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys)
248 {
249 searchval = m_QueueUUIDAvatarMapping[ky];
250
251 if (searchval == AgentID)
252 {
253 removeitems.Add(ky);
254 }
255 }
256
257 foreach (UUID ky in removeitems)
258 m_QueueUUIDAvatarMapping.Remove(ky);
259
260 }
261 }
262
263 private void MakeChildAgent(ScenePresence avatar)
264 {
265 //m_log.DebugFormat("[EVENTQUEUE]: Make Child agent {0} in region {1}.", avatar.UUID, m_scene.RegionInfo.RegionName);
266 //lock (m_ids)
267 // {
268 //if (m_ids.ContainsKey(avatar.UUID))
269 //{
270 // close the event queue.
271 //m_ids[avatar.UUID] = -1;
272 //}
273 //}
274 }
275
276 public void OnRegisterCaps(UUID agentID, Caps caps)
277 {
278 // Register an event queue for the client
279
280 //m_log.DebugFormat(
281 // "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
282 // agentID, caps, m_scene.RegionInfo.RegionName);
283
284 // Let's instantiate a Queue for this agent right now
285 TryGetQueue(agentID);
286
287 string capsBase = "/CAPS/EQG/";
288 UUID EventQueueGetUUID = UUID.Zero;
289
290 lock (m_AvatarQueueUUIDMapping)
291 {
292 // Reuse open queues. The client does!
293 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
294 {
295 m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
296 EventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
297 }
298 else
299 {
300 EventQueueGetUUID = UUID.Random();
301 //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
302 }
303 }
304
305 lock (m_QueueUUIDAvatarMapping)
306 {
307 if (!m_QueueUUIDAvatarMapping.ContainsKey(EventQueueGetUUID))
308 m_QueueUUIDAvatarMapping.Add(EventQueueGetUUID, agentID);
309 }
310
311 lock (m_AvatarQueueUUIDMapping)
312 {
313 if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID))
314 m_AvatarQueueUUIDMapping.Add(agentID, EventQueueGetUUID);
315 }
316
317 // Register this as a caps handler
318 caps.RegisterHandler("EventQueueGet",
319 new RestHTTPHandler("POST", capsBase + EventQueueGetUUID.ToString() + "/",
320 delegate(Hashtable m_dhttpMethod)
321 {
322 return ProcessQueue(m_dhttpMethod, agentID, caps);
323 }));
324
325 // This will persist this beyond the expiry of the caps handlers
326 m_scene.CommsManager.HttpServer.AddHTTPHandler(
327 capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePath2);
328
329 Random rnd = new Random(System.Environment.TickCount);
330 lock (m_ids)
331 {
332 if (!m_ids.ContainsKey(agentID))
333 m_ids.Add(agentID, rnd.Next(30000000));
334 }
335 }
336
337 public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps)
338 {
339 // TODO: this has to be redone to not busy-wait (and block the thread),
340 // TODO: as soon as we have a non-blocking way to handle HTTP-requests.
341
342// if (m_log.IsDebugEnabled)
343// {
344// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ ";
345// foreach (object key in request.Keys)
346// {
347// debug += key.ToString() + "=" + request[key].ToString() + " ";
348// }
349// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name);
350// }
351
352 BlockingLLSDQueue queue = TryGetQueue(agentID);
353 OSD element = queue.Dequeue(15000); // 15s timeout
354
355 Hashtable responsedata = new Hashtable();
356
357 int thisID = 0;
358 lock (m_ids)
359 thisID = m_ids[agentID];
360
361 if (element == null)
362 {
363 //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName);
364 if (thisID == -1) // close-request
365 {
366 m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName);
367 responsedata["int_response_code"] = 404; //501; //410; //404;
368 responsedata["content_type"] = "text/plain";
369 responsedata["keepalive"] = false;
370 responsedata["str_response_string"] = "Closed EQG";
371 return responsedata;
372 }
373 responsedata["int_response_code"] = 502;
374 responsedata["content_type"] = "text/plain";
375 responsedata["keepalive"] = false;
376 responsedata["str_response_string"] = "Upstream error: ";
377 responsedata["error_status_text"] = "Upstream error:";
378 responsedata["http_protocol_version"] = "HTTP/1.0";
379 return responsedata;
380 }
381
382 OSDArray array = new OSDArray();
383 if (element == null) // didn't have an event in 15s
384 {
385 // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
386 array.Add(EventQueueHelper.KeepAliveEvent());
387 m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
388 }
389 else
390 {
391 array.Add(element);
392 while (queue.Count() > 0)
393 {
394 array.Add(queue.Dequeue(1));
395 thisID++;
396 }
397 }
398
399 OSDMap events = new OSDMap();
400 events.Add("events", array);
401
402 events.Add("id", new OSDInteger(thisID));
403 lock (m_ids)
404 {
405 m_ids[agentID] = thisID + 1;
406 }
407
408 responsedata["int_response_code"] = 200;
409 responsedata["content_type"] = "application/xml";
410 responsedata["keepalive"] = false;
411 responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
412 //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
413
414 return responsedata;
415 }
416
417 public Hashtable EventQueuePath2(Hashtable request)
418 {
419 string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/","");
420 // pull off the last "/" in the path.
421 Hashtable responsedata = new Hashtable();
422 capuuid = capuuid.Substring(0, capuuid.Length - 1);
423 capuuid = capuuid.Replace("/CAPS/EQG/", "");
424 UUID AvatarID = UUID.Zero;
425 UUID capUUID = UUID.Zero;
426
427 // parse the path and search for the avatar with it registered
428 if (UUID.TryParse(capuuid, out capUUID))
429 {
430 lock (m_QueueUUIDAvatarMapping)
431 {
432 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
433 {
434 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
435 }
436 }
437 if (AvatarID != UUID.Zero)
438 {
439 return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsHandlerForUser(AvatarID));
440 }
441 else
442 {
443 responsedata["int_response_code"] = 404;
444 responsedata["content_type"] = "text/plain";
445 responsedata["keepalive"] = false;
446 responsedata["str_response_string"] = "Not Found";
447 responsedata["error_status_text"] = "Not Found";
448 responsedata["http_protocol_version"] = "HTTP/1.0";
449 return responsedata;
450 // return 404
451 }
452 }
453 else
454 {
455 responsedata["int_response_code"] = 404;
456 responsedata["content_type"] = "text/plain";
457 responsedata["keepalive"] = false;
458 responsedata["str_response_string"] = "Not Found";
459 responsedata["error_status_text"] = "Not Found";
460 responsedata["http_protocol_version"] = "HTTP/1.0";
461 return responsedata;
462 // return 404
463 }
464
465 }
466
467 public OSD EventQueueFallBack(string path, OSD request, string endpoint)
468 {
469 // This is a fallback element to keep the client from loosing EventQueueGet
470 // Why does CAPS fail sometimes!?
471 m_log.Warn("[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!");
472 string capuuid = path.Replace("/CAPS/EQG/","");
473 capuuid = capuuid.Substring(0, capuuid.Length - 1);
474
475// UUID AvatarID = UUID.Zero;
476 UUID capUUID = UUID.Zero;
477 if (UUID.TryParse(capuuid, out capUUID))
478 {
479/* Don't remove this yet code cleaners!
480 * Still testing this!
481 *
482 lock (m_QueueUUIDAvatarMapping)
483 {
484 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
485 {
486 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
487 }
488 }
489
490
491 if (AvatarID != UUID.Zero)
492 {
493 // Repair the CAP!
494 //OpenSim.Framework.Communications.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID);
495 //string capsBase = "/CAPS/EQG/";
496 //caps.RegisterHandler("EventQueueGet",
497 //new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/",
498 //delegate(Hashtable m_dhttpMethod)
499 //{
500 // return ProcessQueue(m_dhttpMethod, AvatarID, caps);
501 //}));
502 // start new ID sequence.
503 Random rnd = new Random(System.Environment.TickCount);
504 lock (m_ids)
505 {
506 if (!m_ids.ContainsKey(AvatarID))
507 m_ids.Add(AvatarID, rnd.Next(30000000));
508 }
509
510
511 int thisID = 0;
512 lock (m_ids)
513 thisID = m_ids[AvatarID];
514
515 BlockingLLSDQueue queue = GetQueue(AvatarID);
516 OSDArray array = new OSDArray();
517 LLSD element = queue.Dequeue(15000); // 15s timeout
518 if (element == null)
519 {
520
521 array.Add(EventQueueHelper.KeepAliveEvent());
522 }
523 else
524 {
525 array.Add(element);
526 while (queue.Count() > 0)
527 {
528 array.Add(queue.Dequeue(1));
529 thisID++;
530 }
531 }
532 OSDMap events = new OSDMap();
533 events.Add("events", array);
534
535 events.Add("id", new LLSDInteger(thisID));
536
537 lock (m_ids)
538 {
539 m_ids[AvatarID] = thisID + 1;
540 }
541
542 return events;
543 }
544 else
545 {
546 return new LLSD();
547 }
548*
549*/
550 }
551 else
552 {
553 //return new LLSD();
554 }
555
556 return new OSDString("shutdown404!");
557 }
558
559 public void DisableSimulator(ulong handle, UUID avatarID)
560 {
561 OSD item = EventQueueHelper.DisableSimulator(handle);
562 Enqueue(item, avatarID);
563 }
564
565 public void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID)
566 {
567 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint);
568 Enqueue(item, avatarID);
569 }
570
571 public void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath)
572 {
573 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath);
574 Enqueue(item, avatarID);
575 }
576
577 public void TeleportFinishEvent(ulong regionHandle, byte simAccess,
578 IPEndPoint regionExternalEndPoint,
579 uint locationID, uint flags, string capsURL,
580 UUID avatarID)
581 {
582 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
583 locationID, flags, capsURL, avatarID);
584 Enqueue(item, avatarID);
585 }
586
587 public void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
588 IPEndPoint newRegionExternalEndPoint,
589 string capsURL, UUID avatarID, UUID sessionID)
590 {
591 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
592 capsURL, avatarID, sessionID);
593 Enqueue(item, avatarID);
594 }
595
596 public void ChatterboxInvitation(UUID sessionID, string sessionName,
597 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
598 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
599 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
600 {
601 OSD item = EventQueueHelper.ChatterboxInvitation(sessionID, sessionName, fromAgent, message, toAgent, fromName, dialog,
602 timeStamp, offline, parentEstateID, position, ttl, transactionID,
603 fromGroup, binaryBucket);
604 Enqueue(item, toAgent);
605 m_log.InfoFormat("########### eq ChatterboxInvitation #############\n{0}", item);
606
607 }
608
609 public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat,
610 bool isModerator, bool textMute)
611 {
612 OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat,
613 isModerator, textMute);
614 Enqueue(item, toAgent);
615 m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item);
616 }
617
618 public void ParcelProperties(ParcelPropertiesPacket parcelPropertiesPacket, UUID avatarID)
619 {
620 OSD item = Environment.EventQueueHelper.ParcelProperties(parcelPropertiesPacket);
621 Enqueue(item, avatarID);
622 }
623
624 public void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID)
625 {
626 OSD item = EventQueueHelper.GroupMembership(groupUpdate);
627 Enqueue(item, avatarID);
628 }
629 }
630}
diff --git a/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueHelper.cs b/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueHelper.cs
deleted file mode 100644
index b38ddba..0000000
--- a/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueHelper.cs
+++ /dev/null
@@ -1,459 +0,0 @@
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 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 */
27
28using System;
29using System.Net;
30using OpenMetaverse;
31using OpenMetaverse.Packets;
32using OpenMetaverse.StructuredData;
33
34namespace OpenSim.Region.Environment
35{
36 public class EventQueueHelper
37 {
38 private EventQueueHelper() {} // no construction possible, it's an utility class
39
40 private static byte[] ulongToByteArray(ulong uLongValue)
41 {
42 // Reverse endianness of RegionHandle
43 return new byte[]
44 {
45 (byte)((uLongValue >> 56) % 256),
46 (byte)((uLongValue >> 48) % 256),
47 (byte)((uLongValue >> 40) % 256),
48 (byte)((uLongValue >> 32) % 256),
49 (byte)((uLongValue >> 24) % 256),
50 (byte)((uLongValue >> 16) % 256),
51 (byte)((uLongValue >> 8) % 256),
52 (byte)(uLongValue % 256)
53 };
54 }
55
56 private static byte[] uintToByteArray(uint uIntValue)
57 {
58 byte[] resultbytes = Utils.UIntToBytes(uIntValue);
59 if (BitConverter.IsLittleEndian)
60 Array.Reverse(resultbytes);
61
62 return resultbytes;
63 }
64
65 public static OSD buildEvent(string eventName, OSD eventBody)
66 {
67 OSDMap llsdEvent = new OSDMap(2);
68 llsdEvent.Add("message", new OSDString(eventName));
69 llsdEvent.Add("body", eventBody);
70
71 return llsdEvent;
72 }
73
74 public static OSD EnableSimulator(ulong handle, IPEndPoint endPoint)
75 {
76 OSDMap llsdSimInfo = new OSDMap(3);
77
78 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle)));
79 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes()));
80 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port));
81
82 OSDArray arr = new OSDArray(1);
83 arr.Add(llsdSimInfo);
84
85 OSDMap llsdBody = new OSDMap(1);
86 llsdBody.Add("SimulatorInfo", arr);
87
88 return buildEvent("EnableSimulator", llsdBody);
89 }
90
91 public static OSD DisableSimulator(ulong handle)
92 {
93 //OSDMap llsdSimInfo = new OSDMap(1);
94
95 //llsdSimInfo.Add("Handle", new OSDBinary(regionHandleToByteArray(handle)));
96
97 //OSDArray arr = new OSDArray(1);
98 //arr.Add(llsdSimInfo);
99
100 OSDMap llsdBody = new OSDMap(0);
101 //llsdBody.Add("SimulatorInfo", arr);
102
103 return buildEvent("DisableSimulator", llsdBody);
104 }
105
106 public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
107 IPEndPoint newRegionExternalEndPoint,
108 string capsURL, UUID agentID, UUID sessionID)
109 {
110 OSDArray lookAtArr = new OSDArray(3);
111 lookAtArr.Add(OSD.FromReal(lookAt.X));
112 lookAtArr.Add(OSD.FromReal(lookAt.Y));
113 lookAtArr.Add(OSD.FromReal(lookAt.Z));
114
115 OSDArray positionArr = new OSDArray(3);
116 positionArr.Add(OSD.FromReal(pos.X));
117 positionArr.Add(OSD.FromReal(pos.Y));
118 positionArr.Add(OSD.FromReal(pos.Z));
119
120 OSDMap infoMap = new OSDMap(2);
121 infoMap.Add("LookAt", lookAtArr);
122 infoMap.Add("Position", positionArr);
123
124 OSDArray infoArr = new OSDArray(1);
125 infoArr.Add(infoMap);
126
127 OSDMap agentDataMap = new OSDMap(2);
128 agentDataMap.Add("AgentID", OSD.FromUUID(agentID));
129 agentDataMap.Add("SessionID", OSD.FromUUID(sessionID));
130
131 OSDArray agentDataArr = new OSDArray(1);
132 agentDataArr.Add(agentDataMap);
133
134 OSDMap regionDataMap = new OSDMap(4);
135 regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle)));
136 regionDataMap.Add("SeedCapability", OSD.FromString(capsURL));
137 regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes()));
138 regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port));
139
140 OSDArray regionDataArr = new OSDArray(1);
141 regionDataArr.Add(regionDataMap);
142
143 OSDMap llsdBody = new OSDMap(3);
144 llsdBody.Add("Info", infoArr);
145 llsdBody.Add("AgentData", agentDataArr);
146 llsdBody.Add("RegionData", regionDataArr);
147
148 return buildEvent("CrossedRegion", llsdBody);
149 }
150
151 public static OSD TeleportFinishEvent(
152 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
153 uint locationID, uint flags, string capsURL, UUID agentID)
154 {
155 OSDMap info = new OSDMap();
156 info.Add("AgentID", OSD.FromUUID(agentID));
157 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this?
158 info.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(regionHandle)));
159 info.Add("SeedCapability", OSD.FromString(capsURL));
160 info.Add("SimAccess", OSD.FromInteger(simAccess));
161 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes()));
162 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
163 info.Add("TeleportFlags", OSD.FromBinary(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
164
165 OSDArray infoArr = new OSDArray();
166 infoArr.Add(info);
167
168 OSDMap body = new OSDMap();
169 body.Add("Info", infoArr);
170
171 return buildEvent("TeleportFinish", body);
172 }
173
174 public static OSD ScriptRunningReplyEvent(UUID objectID, UUID itemID, bool running, bool mono)
175 {
176 OSDMap script = new OSDMap();
177 script.Add("ObjectID", OSD.FromUUID(objectID));
178 script.Add("ItemID", OSD.FromUUID(itemID));
179 script.Add("Running", OSD.FromBoolean(running));
180 script.Add("Mono", OSD.FromBoolean(mono));
181
182 OSDArray scriptArr = new OSDArray();
183 scriptArr.Add(script);
184
185 OSDMap body = new OSDMap();
186 body.Add("Script", scriptArr);
187
188 return buildEvent("ScriptRunningReply", body);
189 }
190
191 public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap)
192 {
193 OSDMap body = new OSDMap(3);
194 body.Add("agent-id", new OSDUUID(agentID));
195 body.Add("sim-ip-and-port", new OSDString(simIpAndPort));
196 body.Add("seed-capability", new OSDString(seedcap));
197
198 return buildEvent("EstablishAgentCommunication", body);
199 }
200
201 public static OSD KeepAliveEvent()
202 {
203 return buildEvent("FAKEEVENT", new OSDMap());
204 }
205
206 public static OSD AgentParams(UUID agentID, bool checkEstate, int godLevel, bool limitedToEstate)
207 {
208 OSDMap body = new OSDMap(4);
209
210 body.Add("agent_id", new OSDUUID(agentID));
211 body.Add("check_estate", new OSDInteger(checkEstate ? 1 : 0));
212 body.Add("god_level", new OSDInteger(godLevel));
213 body.Add("limited_to_estate", new OSDInteger(limitedToEstate ? 1 : 0));
214
215 return body;
216 }
217
218 public static OSD InstantMessageParams(UUID fromAgent, string message, UUID toAgent,
219 string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID,
220 Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
221 {
222 OSDMap messageParams = new OSDMap(15);
223 messageParams.Add("type", new OSDInteger((int)dialog));
224
225 OSDArray positionArray = new OSDArray(3);
226 positionArray.Add(OSD.FromReal(position.X));
227 positionArray.Add(OSD.FromReal(position.Y));
228 positionArray.Add(OSD.FromReal(position.Z));
229 messageParams.Add("position", positionArray);
230
231 messageParams.Add("region_id", new OSDUUID(UUID.Zero));
232 messageParams.Add("to_id", new OSDUUID(toAgent));
233 messageParams.Add("source", new OSDInteger(0));
234
235 OSDMap data = new OSDMap(1);
236 data.Add("binary_bucket", OSD.FromBinary(binaryBucket));
237 messageParams.Add("data", data);
238 messageParams.Add("message", new OSDString(message));
239 messageParams.Add("id", new OSDUUID(transactionID));
240 messageParams.Add("from_name", new OSDString(fromName));
241 messageParams.Add("timestamp", new OSDInteger((int)timeStamp));
242 messageParams.Add("offline", new OSDInteger(offline ? 1 : 0));
243 messageParams.Add("parent_estate_id", new OSDInteger(parentEstateID));
244 messageParams.Add("ttl", new OSDInteger((int)ttl));
245 messageParams.Add("from_id", new OSDUUID(fromAgent));
246 messageParams.Add("from_group", new OSDInteger(fromGroup ? 1 : 0));
247
248 return messageParams;
249 }
250
251 public static OSD InstantMessage(UUID fromAgent, string message, UUID toAgent,
252 string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID,
253 Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket,
254 bool checkEstate, int godLevel, bool limitedToEstate)
255 {
256 OSDMap im = new OSDMap(2);
257 im.Add("message_params", InstantMessageParams(fromAgent, message, toAgent,
258 fromName, dialog, timeStamp, offline, parentEstateID,
259 position, ttl, transactionID, fromGroup, binaryBucket));
260
261 im.Add("agent_params", AgentParams(fromAgent, checkEstate, godLevel, limitedToEstate));
262
263 return im;
264 }
265
266
267 public static OSD ChatterboxInvitation(UUID sessionID, string sessionName,
268 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
269 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
270 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
271 {
272 OSDMap body = new OSDMap(5);
273 body.Add("session_id", new OSDUUID(sessionID));
274 body.Add("from_name", new OSDString(fromName));
275 body.Add("session_name", new OSDString(sessionName));
276 body.Add("from_id", new OSDUUID(fromAgent));
277
278 body.Add("instantmessage", InstantMessage(fromAgent, message, toAgent,
279 fromName, dialog, timeStamp, offline, parentEstateID, position,
280 ttl, transactionID, fromGroup, binaryBucket, true, 0, true));
281
282 OSDMap chatterboxInvitation = new OSDMap(2);
283 chatterboxInvitation.Add("message", new OSDString("ChatterBoxInvitation"));
284 chatterboxInvitation.Add("body", body);
285 return chatterboxInvitation;
286 }
287
288 public static OSD ChatterBoxSessionAgentListUpdates(UUID sessionID,
289 UUID agentID, bool canVoiceChat, bool isModerator, bool textMute)
290 {
291 OSDMap body = new OSDMap();
292 OSDMap agentUpdates = new OSDMap();
293 OSDMap infoDetail = new OSDMap();
294 OSDMap mutes = new OSDMap();
295
296 mutes.Add("text", OSD.FromBoolean(textMute));
297 infoDetail.Add("can_voice_chat", OSD.FromBoolean(canVoiceChat));
298 infoDetail.Add("is_moderator", OSD.FromBoolean(isModerator));
299 infoDetail.Add("mutes", mutes);
300 OSDMap info = new OSDMap();
301 info.Add("info", infoDetail);
302 agentUpdates.Add(agentID.ToString(), info);
303 body.Add("agent_updates", agentUpdates);
304 body.Add("session_id", OSD.FromUUID(sessionID));
305 body.Add("updates", new OSD());
306
307 OSDMap chatterBoxSessionAgentListUpdates = new OSDMap();
308 chatterBoxSessionAgentListUpdates.Add("message", OSD.FromString("ChatterBoxSessionAgentListUpdates"));
309 chatterBoxSessionAgentListUpdates.Add("body", body);
310
311 return chatterBoxSessionAgentListUpdates;
312 }
313
314 public static OSD ParcelProperties(ParcelPropertiesPacket parcelPropertiesPacket)
315 {
316 OSDMap parcelProperties = new OSDMap();
317 OSDMap body = new OSDMap();
318
319 OSDArray ageVerificationBlock = new OSDArray();
320 OSDMap ageVerificationMap = new OSDMap();
321 ageVerificationMap.Add("RegionDenyAgeUnverified",
322 OSD.FromBoolean(parcelPropertiesPacket.AgeVerificationBlock.RegionDenyAgeUnverified));
323 ageVerificationBlock.Add(ageVerificationMap);
324 body.Add("AgeVerificationBlock", ageVerificationBlock);
325
326 // LL sims send media info in this event queue message but it's not in the UDP
327 // packet we construct this event queue message from. This should be refactored in
328 // other areas of the code so it can all be send in the same message. Until then we will
329 // still send the media info via UDP
330
331 //OSDArray mediaData = new OSDArray();
332 //OSDMap mediaDataMap = new OSDMap();
333 //mediaDataMap.Add("MediaDesc", OSD.FromString(""));
334 //mediaDataMap.Add("MediaHeight", OSD.FromInteger(0));
335 //mediaDataMap.Add("MediaLoop", OSD.FromInteger(0));
336 //mediaDataMap.Add("MediaType", OSD.FromString("type/type"));
337 //mediaDataMap.Add("MediaWidth", OSD.FromInteger(0));
338 //mediaDataMap.Add("ObscureMedia", OSD.FromInteger(0));
339 //mediaDataMap.Add("ObscureMusic", OSD.FromInteger(0));
340 //mediaData.Add(mediaDataMap);
341 //body.Add("MediaData", mediaData);
342
343 OSDArray parcelData = new OSDArray();
344 OSDMap parcelDataMap = new OSDMap();
345 OSDArray AABBMax = new OSDArray(3);
346 AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.X));
347 AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.Y));
348 AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.Z));
349 parcelDataMap.Add("AABBMax", AABBMax);
350
351 OSDArray AABBMin = new OSDArray(3);
352 AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.X));
353 AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.Y));
354 AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.Z));
355 parcelDataMap.Add("AABBMin", AABBMin);
356
357 parcelDataMap.Add("Area", OSD.FromInteger(parcelPropertiesPacket.ParcelData.Area));
358 parcelDataMap.Add("AuctionID", OSD.FromBinary(uintToByteArray(parcelPropertiesPacket.ParcelData.AuctionID)));
359 parcelDataMap.Add("AuthBuyerID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.AuthBuyerID));
360 parcelDataMap.Add("Bitmap", OSD.FromBinary(parcelPropertiesPacket.ParcelData.Bitmap));
361 parcelDataMap.Add("Category", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.Category));
362 parcelDataMap.Add("ClaimDate", OSD.FromInteger(parcelPropertiesPacket.ParcelData.ClaimDate));
363 parcelDataMap.Add("ClaimPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.ClaimPrice));
364 parcelDataMap.Add("Desc", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc)));
365 parcelDataMap.Add("GroupID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.GroupID));
366 parcelDataMap.Add("GroupPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.GroupPrims));
367 parcelDataMap.Add("IsGroupOwned", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.IsGroupOwned));
368 parcelDataMap.Add("LandingType", OSD.FromInteger(parcelPropertiesPacket.ParcelData.LandingType));
369 parcelDataMap.Add("LocalID", OSD.FromInteger(parcelPropertiesPacket.ParcelData.LocalID));
370 parcelDataMap.Add("MaxPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.MaxPrims));
371 parcelDataMap.Add("MediaAutoScale", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.MediaAutoScale));
372 parcelDataMap.Add("MediaID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.MediaID));
373 parcelDataMap.Add("MediaURL", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL)));
374 parcelDataMap.Add("MusicURL", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL)));
375 parcelDataMap.Add("Name", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name)));
376 parcelDataMap.Add("OtherCleanTime", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherCleanTime));
377 parcelDataMap.Add("OtherCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherCount));
378 parcelDataMap.Add("OtherPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherPrims));
379 parcelDataMap.Add("OwnerID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.OwnerID));
380 parcelDataMap.Add("OwnerPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OwnerPrims));
381 parcelDataMap.Add("ParcelFlags", OSD.FromBinary(uintToByteArray(parcelPropertiesPacket.ParcelData.ParcelFlags)));
382 parcelDataMap.Add("ParcelPrimBonus", OSD.FromReal(parcelPropertiesPacket.ParcelData.ParcelPrimBonus));
383 parcelDataMap.Add("PassHours", OSD.FromReal(parcelPropertiesPacket.ParcelData.PassHours));
384 parcelDataMap.Add("PassPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.PassPrice));
385 parcelDataMap.Add("PublicCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.PublicCount));
386 parcelDataMap.Add("RegionDenyAnonymous", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyAnonymous));
387 parcelDataMap.Add("RegionDenyIdentified", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyIdentified));
388 parcelDataMap.Add("RegionDenyTransacted", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyTransacted));
389
390 parcelDataMap.Add("RegionPushOverride", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionPushOverride));
391 parcelDataMap.Add("RentPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.RentPrice));
392 parcelDataMap.Add("RequestResult", OSD.FromInteger(parcelPropertiesPacket.ParcelData.RequestResult));
393 parcelDataMap.Add("SalePrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SalePrice));
394 parcelDataMap.Add("SelectedPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SelectedPrims));
395 parcelDataMap.Add("SelfCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SelfCount));
396 parcelDataMap.Add("SequenceID", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SequenceID));
397 parcelDataMap.Add("SimWideMaxPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SimWideMaxPrims));
398 parcelDataMap.Add("SimWideTotalPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SimWideTotalPrims));
399 parcelDataMap.Add("SnapSelection", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.SnapSelection));
400 parcelDataMap.Add("SnapshotID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.SnapshotID));
401 parcelDataMap.Add("Status", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.Status));
402 parcelDataMap.Add("TotalPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.TotalPrims));
403
404 OSDArray UserLocation = new OSDArray(3);
405 UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.X));
406 UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.Y));
407 UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.Z));
408 parcelDataMap.Add("UserLocation", UserLocation);
409
410 OSDArray UserLookAt = new OSDArray(3);
411 UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.X));
412 UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.Y));
413 UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.Z));
414 parcelDataMap.Add("UserLookAt", UserLookAt);
415
416 parcelData.Add(parcelDataMap);
417 body.Add("ParcelData", parcelData);
418 parcelProperties.Add("body", body);
419 parcelProperties.Add("message", OSD.FromString("ParcelProperties"));
420
421 return parcelProperties;
422 }
423
424 public static OSD GroupMembership(AgentGroupDataUpdatePacket groupUpdatePacket)
425 {
426 OSDMap groupUpdate = new OSDMap();
427 groupUpdate.Add("message", OSD.FromString("AgentGroupDataUpdate"));
428
429 OSDMap body = new OSDMap();
430 OSDArray agentData = new OSDArray();
431 OSDMap agentDataMap = new OSDMap();
432 agentDataMap.Add("AgentID", OSD.FromUUID(groupUpdatePacket.AgentData.AgentID));
433 agentData.Add(agentDataMap);
434 body.Add("AgentData", agentData);
435
436 OSDArray groupData = new OSDArray();
437
438 foreach (AgentGroupDataUpdatePacket.GroupDataBlock groupDataBlock in groupUpdatePacket.GroupData)
439 {
440 OSDMap groupDataMap = new OSDMap();
441 groupDataMap.Add("ListInProfile", OSD.FromBoolean(false));
442 groupDataMap.Add("GroupID", OSD.FromUUID(groupDataBlock.GroupID));
443 groupDataMap.Add("GroupInsigniaID", OSD.FromUUID(groupDataBlock.GroupInsigniaID));
444 groupDataMap.Add("Contribution", OSD.FromInteger(groupDataBlock.Contribution));
445 groupDataMap.Add("GroupPowers", OSD.FromBinary(ulongToByteArray(groupDataBlock.GroupPowers)));
446 groupDataMap.Add("GroupName", OSD.FromString(Utils.BytesToString(groupDataBlock.GroupName)));
447 groupDataMap.Add("AcceptNotices", OSD.FromBoolean(groupDataBlock.AcceptNotices));
448
449 groupData.Add(groupDataMap);
450
451 }
452 body.Add("GroupData", groupData);
453 groupUpdate.Add("body", body);
454
455 return groupUpdate;
456 }
457
458 }
459}
diff --git a/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Command.cs b/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Command.cs
deleted file mode 100644
index b6114e8..0000000
--- a/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Command.cs
+++ /dev/null
@@ -1,216 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.Environment.Modules.Framework.InterfaceCommander
33{
34 /// <summary>
35 /// A single function call encapsulated in a class which enforces arguments when passing around as Object[]'s.
36 /// Used for console commands and script API generation
37 /// </summary>
38 public class Command : ICommand
39 {
40 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 private List<CommandArgument> m_args = new List<CommandArgument>();
42
43 private Action<object[]> m_command;
44 private string m_help;
45 private string m_name;
46 private CommandIntentions m_intentions; //A permission type system could implement this and know what a command intends on doing.
47
48 public Command(string name, CommandIntentions intention, Action<Object[]> command, string help)
49 {
50 m_name = name;
51 m_command = command;
52 m_help = help;
53 m_intentions = intention;
54 }
55
56 #region ICommand Members
57
58 public void AddArgument(string name, string helptext, string type)
59 {
60 m_args.Add(new CommandArgument(name, helptext, type));
61 }
62
63 public string Name
64 {
65 get { return m_name; }
66 }
67
68 public CommandIntentions Intentions
69 {
70 get { return m_intentions; }
71 }
72
73 public string Help
74 {
75 get { return m_help; }
76 }
77
78 public Dictionary<string, string> Arguments
79 {
80 get
81 {
82 Dictionary<string, string> tmp = new Dictionary<string, string>();
83 foreach (CommandArgument arg in m_args)
84 {
85 tmp.Add(arg.Name, arg.ArgumentType);
86 }
87 return tmp;
88 }
89 }
90
91 public string ShortHelp()
92 {
93 string help = m_name;
94
95 foreach (CommandArgument arg in m_args)
96 {
97 help += " <" + arg.Name + ">";
98 }
99
100 return help;
101 }
102
103 public void ShowConsoleHelp()
104 {
105 Console.WriteLine("== " + Name + " ==");
106 Console.WriteLine(m_help);
107 Console.WriteLine("= Parameters =");
108 foreach (CommandArgument arg in m_args)
109 {
110 Console.WriteLine("* " + arg.Name + " (" + arg.ArgumentType + ")");
111 Console.WriteLine("\t" + arg.HelpText);
112 }
113 }
114
115 public void Run(Object[] args)
116 {
117 Object[] cleanArgs = new Object[m_args.Count];
118
119 if (args.Length < cleanArgs.Length)
120 {
121 Console.WriteLine("ERROR: Missing " + (cleanArgs.Length - args.Length) + " argument(s)");
122 ShowConsoleHelp();
123 return;
124 }
125 if (args.Length > cleanArgs.Length)
126 {
127 Console.WriteLine("ERROR: Too many arguments for this command. Type '<module> <command> help' for help.");
128 return;
129 }
130
131 int i = 0;
132 foreach (Object arg in args)
133 {
134 if (string.IsNullOrEmpty(arg.ToString()))
135 {
136 Console.WriteLine("ERROR: Empty arguments are not allowed");
137 return;
138 }
139 try
140 {
141 switch (m_args[i].ArgumentType)
142 {
143 case "String":
144 m_args[i].ArgumentValue = arg.ToString();
145 break;
146 case "Integer":
147 m_args[i].ArgumentValue = Int32.Parse(arg.ToString());
148 break;
149 case "Double":
150 m_args[i].ArgumentValue = Double.Parse(arg.ToString());
151 break;
152 case "Boolean":
153 m_args[i].ArgumentValue = Boolean.Parse(arg.ToString());
154 break;
155 default:
156 Console.WriteLine("ERROR: Unknown desired type for argument " + m_args[i].Name + " on command " + m_name);
157 break;
158 }
159 }
160 catch (FormatException)
161 {
162 Console.WriteLine("ERROR: Argument number " + (i + 1) +
163 " (" + m_args[i].Name + ") must be a valid " +
164 m_args[i].ArgumentType.ToLower() + ".");
165 return;
166 }
167 cleanArgs[i] = m_args[i].ArgumentValue;
168
169 i++;
170 }
171
172 m_command.Invoke(cleanArgs);
173 }
174
175 #endregion
176 }
177
178 /// <summary>
179 /// A single command argument, contains name, type and at runtime, value.
180 /// </summary>
181 public class CommandArgument
182 {
183 private string m_help;
184 private string m_name;
185 private string m_type;
186 private Object m_val;
187
188 public CommandArgument(string name, string help, string type)
189 {
190 m_name = name;
191 m_help = help;
192 m_type = type;
193 }
194
195 public string Name
196 {
197 get { return m_name; }
198 }
199
200 public string HelpText
201 {
202 get { return m_help; }
203 }
204
205 public string ArgumentType
206 {
207 get { return m_type; }
208 }
209
210 public Object ArgumentValue
211 {
212 get { return m_val; }
213 set { m_val = value; }
214 }
215 }
216}
diff --git a/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Commander.cs b/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Commander.cs
deleted file mode 100644
index cd66295..0000000
--- a/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Commander.cs
+++ /dev/null
@@ -1,182 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using log4net;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35
36namespace OpenSim.Region.Environment.Modules.Framework.InterfaceCommander
37{
38 /// <summary>
39 /// A class to enable modules to register console and script commands, which enforces typing and valid input.
40 /// </summary>
41 public class Commander : ICommander
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 /// <value>
46 /// Used in runtime class generation
47 /// </summary>
48 private string m_generatedApiClassName;
49
50 public string Name
51 {
52 get { return m_name; }
53 }
54 private string m_name;
55
56 public string Help
57 {
58 get
59 {
60 StringBuilder sb = new StringBuilder();
61
62 sb.AppendLine("=== " + m_name + " ===");
63
64 foreach (ICommand com in m_commands.Values)
65 {
66 sb.AppendLine("* " + Name + " " + com.Name + " - " + com.Help);
67 }
68
69 return sb.ToString();
70 }
71 }
72
73 /// <summary>
74 /// Constructor
75 /// </summary>
76 /// <param name="name"></param>
77 public Commander(string name)
78 {
79 m_name = name;
80 m_generatedApiClassName = m_name[0].ToString().ToUpper();
81
82 if (m_name.Length > 1)
83 m_generatedApiClassName += m_name.Substring(1);
84 }
85
86 public Dictionary<string, ICommand> Commands
87 {
88 get { return m_commands; }
89 }
90 private Dictionary<string, ICommand> m_commands = new Dictionary<string, ICommand>();
91
92 #region ICommander Members
93
94 public void RegisterCommand(string commandName, ICommand command)
95 {
96 m_commands[commandName] = command;
97 }
98
99 /// <summary>
100 /// Generates a runtime C# class which can be compiled and inserted via reflection to enable modules to register new script commands
101 /// </summary>
102 /// <returns>Returns C# source code to create a binding</returns>
103 public string GenerateRuntimeAPI()
104 {
105 string classSrc = "\n\tpublic class " + m_generatedApiClassName + " {\n";
106 foreach (ICommand com in m_commands.Values)
107 {
108 classSrc += "\tpublic void " + EscapeRuntimeAPICommand(com.Name) + "( ";
109 foreach (KeyValuePair<string, string> arg in com.Arguments)
110 {
111 classSrc += arg.Value + " " + Util.Md5Hash(arg.Key) + ",";
112 }
113 classSrc = classSrc.Remove(classSrc.Length - 1); // Delete the last comma
114 classSrc += " )\n\t{\n";
115 classSrc += "\t\tObject[] args = new Object[" + com.Arguments.Count.ToString() + "];\n";
116 int i = 0;
117 foreach (KeyValuePair<string, string> arg in com.Arguments)
118 {
119 classSrc += "\t\targs[" + i.ToString() + "] = " + Util.Md5Hash(arg.Key) + " " + ";\n";
120 i++;
121 }
122 classSrc += "\t\tGetCommander(\"" + m_name + "\").Run(\"" + com.Name + "\", args);\n";
123 classSrc += "\t}\n";
124 }
125 classSrc += "}\n";
126
127 return classSrc;
128 }
129
130 /// <summary>
131 /// Runs a specified function with attached arguments
132 /// *** <b>DO NOT CALL DIRECTLY.</b> ***
133 /// Call ProcessConsoleCommand instead if handling human input.
134 /// </summary>
135 /// <param name="function">The function name to call</param>
136 /// <param name="args">The function parameters</param>
137 public void Run(string function, object[] args)
138 {
139 m_commands[function].Run(args);
140 }
141
142 public void ProcessConsoleCommand(string function, string[] args)
143 {
144 if (m_commands.ContainsKey(function))
145 {
146 if (args.Length > 0 && args[0] == "help")
147 {
148 m_commands[function].ShowConsoleHelp();
149 }
150 else
151 {
152 m_commands[function].Run(args);
153 }
154 }
155 else
156 {
157 if (function == "api")
158 {
159 m_log.Info(GenerateRuntimeAPI());
160 }
161 else
162 {
163 if (function != "help")
164 Console.WriteLine("ERROR: Invalid command - No such command exists");
165
166 Console.Write(Help);
167 }
168 }
169 }
170
171 #endregion
172
173 private string EscapeRuntimeAPICommand(string command)
174 {
175 command = command.Replace('-', '_');
176 StringBuilder tmp = new StringBuilder(command);
177 tmp[0] = tmp[0].ToString().ToUpper().ToCharArray()[0];
178
179 return tmp.ToString();
180 }
181 }
182} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs b/OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs
deleted file mode 100644
index edf1231..0000000
--- a/OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs
+++ /dev/null
@@ -1,43 +0,0 @@
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 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 */
27
28using OpenSim.Framework;
29using OpenSim.Region.Framework.Scenes;
30
31namespace OpenSim.Region.Environment.Modules.Grid.Interregion
32{
33 public interface IInterregionModule
34 {
35 void RegisterMethod<T>(T e);
36 bool HasInterface<T>(Location loc);
37 T RequestInterface<T>(Location loc);
38 T[] RequestInterface<T>();
39 Location GetLocationByDirection(Scene scene, InterregionModule.Direction dir);
40 void internal_CreateRemotingObjects();
41 void RegisterRemoteRegion(string uri);
42 }
43} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs b/OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs
deleted file mode 100644
index cb571e4..0000000
--- a/OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs
+++ /dev/null
@@ -1,199 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Runtime.Remoting;
31using System.Runtime.Remoting.Channels;
32using System.Runtime.Remoting.Channels.Tcp;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38namespace OpenSim.Region.Environment.Modules.Grid.Interregion
39{
40 public class InterregionModule : IInterregionModule, IRegionModule
41 {
42 #region Direction enum
43
44 public enum Direction
45 {
46 North,
47 NorthEast,
48 East,
49 SouthEast,
50 South,
51 SouthWest,
52 West,
53 NorthWest
54 }
55
56 #endregion
57
58 private readonly Dictionary<Type, Object> m_interfaces = new Dictionary<Type, object>();
59 private readonly Object m_lockObject = new object();
60 private readonly List<Location> m_myLocations = new List<Location>();
61
62 private readonly Dictionary<Location, string[]> m_neighbourInterfaces = new Dictionary<Location, string[]>();
63 private readonly Dictionary<Location, RemotingObject> m_neighbourRemote = new Dictionary<Location, RemotingObject>();
64 // private IConfigSource m_config;
65 private const bool m_enabled = false;
66
67 private RemotingObject m_myRemote;
68 private TcpChannel m_tcpChannel;
69 private int m_tcpPort = 10101;
70
71 #region IInterregionModule Members
72
73 public void internal_CreateRemotingObjects()
74 {
75 lock (m_lockObject)
76 {
77 if (m_tcpChannel == null)
78 {
79 m_myRemote = new RemotingObject(m_interfaces, m_myLocations.ToArray());
80 m_tcpChannel = new TcpChannel(m_tcpPort);
81
82 ChannelServices.RegisterChannel(m_tcpChannel, false);
83 RemotingServices.Marshal(m_myRemote, "OpenSimRemote2", typeof (RemotingObject));
84 }
85 }
86 }
87
88 public void RegisterMethod<T>(T e)
89 {
90 m_interfaces[typeof (T)] = e;
91 }
92
93 public bool HasInterface<T>(Location loc)
94 {
95 foreach (string val in m_neighbourInterfaces[loc])
96 {
97 if (val == typeof (T).FullName)
98 {
99 return true;
100 }
101 }
102 return false;
103 }
104
105 public T RequestInterface<T>(Location loc)
106 {
107 if (m_neighbourRemote.ContainsKey(loc))
108 {
109 return m_neighbourRemote[loc].RequestInterface<T>();
110 }
111 throw new IndexOutOfRangeException("No neighbour availible at that location");
112 }
113
114 public T[] RequestInterface<T>()
115 {
116 List<T> m_t = new List<T>();
117 foreach (RemotingObject remote in m_neighbourRemote.Values)
118 {
119 try
120 {
121 m_t.Add(remote.RequestInterface<T>());
122 }
123 catch (NotSupportedException)
124 {
125 }
126 }
127 return m_t.ToArray();
128 }
129
130 public Location GetLocationByDirection(Scene scene, Direction dir)
131 {
132 return new Location(0, 0);
133 }
134
135 public void RegisterRemoteRegion(string uri)
136 {
137 RegisterRemotingInterface((RemotingObject) Activator.GetObject(typeof (RemotingObject), uri));
138 }
139
140 #endregion
141
142 #region IRegionModule Members
143
144 public void Initialise(Scene scene, IConfigSource source)
145 {
146 m_myLocations.Add(new Location((int) scene.RegionInfo.RegionLocX,
147 (int) scene.RegionInfo.RegionLocY));
148 // m_config = source;
149
150 scene.RegisterModuleInterface<IInterregionModule>(this);
151 }
152
153 public void PostInitialise()
154 {
155 // Commenting out to remove 'unreachable code' warning since m_enabled is never true
156// if (m_enabled)
157// {
158// try
159// {
160// m_tcpPort = m_config.Configs["Comms"].GetInt("remoting_port", m_tcpPort);
161// }
162// catch
163// {
164// }
165//
166// internal_CreateRemotingObjects();
167// }
168 }
169
170 public void Close()
171 {
172 if (null != m_tcpChannel)
173 ChannelServices.UnregisterChannel(m_tcpChannel);
174 }
175
176 public string Name
177 {
178 get { return "InterregionModule"; }
179 }
180
181 public bool IsSharedModule
182 {
183 get { return true; }
184 }
185
186 #endregion
187
188 private void RegisterRemotingInterface(RemotingObject remote)
189 {
190 Location[] locs = remote.GetLocations();
191 string[] interfaces = remote.GetInterfaces();
192 foreach (Location loc in locs)
193 {
194 m_neighbourInterfaces[loc] = interfaces;
195 m_neighbourRemote[loc] = remote;
196 }
197 }
198 }
199}
diff --git a/OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs b/OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs
deleted file mode 100644
index 47357d2..0000000
--- a/OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs
+++ /dev/null
@@ -1,77 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using OpenSim.Framework;
31
32namespace OpenSim.Region.Environment.Modules.Grid.Interregion
33{
34 public class RemotingObject : MarshalByRefObject
35 {
36 private readonly Location[] m_coords;
37 private readonly Dictionary<Type, Object> m_interfaces = new Dictionary<Type, object>();
38
39 public RemotingObject(Dictionary<Type, Object> myInterfaces, Location[] coords)
40 {
41 m_interfaces = myInterfaces;
42 m_coords = coords;
43 }
44
45 public Location[] GetLocations()
46 {
47 return (Location[]) m_coords.Clone();
48 }
49
50 public string[] GetInterfaces()
51 {
52 string[] interfaces = new string[m_interfaces.Count];
53 int i = 0;
54
55 foreach (KeyValuePair<Type, object> pair in m_interfaces)
56 {
57 interfaces[i++] = pair.Key.FullName;
58 }
59
60 return interfaces;
61 }
62
63 /// <summary>
64 /// Returns a registered interface availible to neighbouring regions.
65 /// </summary>
66 /// <typeparam name="T">The type of interface you wish to request</typeparam>
67 /// <returns>A MarshalByRefObject inherited from this region inheriting the interface requested.</returns>
68 /// <remarks>All registered interfaces <b>MUST</b> inherit from MarshalByRefObject and use only serialisable types.</remarks>
69 public T RequestInterface<T>()
70 {
71 if (m_interfaces.ContainsKey(typeof (T)))
72 return (T) m_interfaces[typeof (T)];
73
74 throw new NotSupportedException("No such interface registered.");
75 }
76 }
77}
diff --git a/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneAssetService.cs b/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneAssetService.cs
deleted file mode 100644
index 4cb1c20..0000000
--- a/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneAssetService.cs
+++ /dev/null
@@ -1,201 +0,0 @@
1/**
2 * Copyright (c) 2008, Contributors. All rights reserved.
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the Organizations nor the names of Individual
14 * Contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29using System;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33
34using log4net;
35using Nini.Config;
36
37using OpenMetaverse;
38
39using OpenSim.Framework;
40using OpenSim.Framework.Communications;
41using OpenSim.Framework.Communications.Cache;
42using OpenSim.Framework.Servers;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using OpenSim.Grid.AssetServer;
46using OpenSim.Data;
47
48namespace OpenSim.Region.Environment.Modules.Hypergrid
49{
50 public class HGStandaloneAssetService : IRegionModule
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 private static bool initialized = false;
54 private static bool enabled = false;
55
56 Scene m_scene;
57 //AssetService m_assetService;
58
59 #region IRegionModule interface
60
61 public void Initialise(Scene scene, IConfigSource config)
62 {
63 if (!initialized)
64 {
65 initialized = true;
66 m_scene = scene;
67
68 // This module is only on for standalones in hypergrid mode
69 enabled = !config.Configs["Startup"].GetBoolean("gridmode", true) && config.Configs["Startup"].GetBoolean("hypergrid", false);
70 }
71 }
72
73 public void PostInitialise()
74 {
75 if (enabled)
76 {
77 m_log.Info("[HGStandaloneAssetService]: Starting...");
78
79 //m_assetService = new AssetService(m_scene);
80 new AssetService(m_scene);
81 }
82 }
83
84 public void Close()
85 {
86 }
87
88 public string Name
89 {
90 get { return "HGStandaloneAssetService"; }
91 }
92
93 public bool IsSharedModule
94 {
95 get { return true; }
96 }
97
98 #endregion
99
100 }
101
102 public class AssetService
103 {
104 private IUserService m_userService;
105 private bool m_doLookup = false;
106
107 public bool DoLookup
108 {
109 get { return m_doLookup; }
110 set { m_doLookup = value; }
111 }
112 private static readonly ILog m_log
113 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
114
115 public AssetService(Scene m_scene)
116 {
117 AddHttpHandlers(m_scene);
118 m_userService = m_scene.CommsManager.UserService;
119 }
120
121 protected void AddHttpHandlers(Scene m_scene)
122 {
123 IAssetDataPlugin m_assetProvider = ((AssetServerBase)m_scene.AssetCache.AssetServer).AssetProviderPlugin;
124
125 BaseHttpServer httpServer = m_scene.CommsManager.HttpServer;
126 httpServer.AddStreamHandler(new GetAssetStreamHandler(m_assetProvider));
127 httpServer.AddStreamHandler(new PostAssetStreamHandler(m_assetProvider));
128
129 }
130
131 ///// <summary>
132 ///// Check that the source of an inventory request is one that we trust.
133 ///// </summary>
134 ///// <param name="peer"></param>
135 ///// <returns></returns>
136 //public bool CheckTrustSource(IPEndPoint peer)
137 //{
138 // if (m_doLookup)
139 // {
140 // m_log.InfoFormat("[GRID AGENT INVENTORY]: Checking trusted source {0}", peer);
141 // UriBuilder ub = new UriBuilder(m_userserver_url);
142 // IPAddress[] uaddrs = Dns.GetHostAddresses(ub.Host);
143 // foreach (IPAddress uaddr in uaddrs)
144 // {
145 // if (uaddr.Equals(peer.Address))
146 // {
147 // return true;
148 // }
149 // }
150
151 // m_log.WarnFormat(
152 // "[GRID AGENT INVENTORY]: Rejecting request since source {0} was not in the list of trusted sources",
153 // peer);
154
155 // return false;
156 // }
157 // else
158 // {
159 // return true;
160 // }
161 //}
162
163 /// <summary>
164 /// Check that the source of an inventory request for a particular agent is a current session belonging to
165 /// that agent.
166 /// </summary>
167 /// <param name="session_id"></param>
168 /// <param name="avatar_id"></param>
169 /// <returns></returns>
170 public bool CheckAuthSession(string session_id, string avatar_id)
171 {
172 if (m_doLookup)
173 {
174 m_log.InfoFormat("[HGStandaloneInvService]: checking authed session {0} {1}", session_id, avatar_id);
175 UUID userID = UUID.Zero;
176 UUID sessionID = UUID.Zero;
177 UUID.TryParse(avatar_id, out userID);
178 UUID.TryParse(session_id, out sessionID);
179 if (userID.Equals(UUID.Zero) || sessionID.Equals(UUID.Zero))
180 {
181 m_log.Info("[HGStandaloneInvService]: Invalid user or session id " + avatar_id + "; " + session_id);
182 return false;
183 }
184 UserProfileData userProfile = m_userService.GetUserProfile(userID);
185 if (userProfile != null && userProfile.CurrentAgent != null &&
186 userProfile.CurrentAgent.SessionID == sessionID)
187 {
188 m_log.Info("[HGStandaloneInvService]: user is logged in and session is valid. Authorizing access.");
189 return true;
190 }
191
192 m_log.Warn("[HGStandaloneInvService]: unknown user or session_id, request rejected");
193 return false;
194 }
195 else
196 {
197 return true;
198 }
199 }
200 }
201}
diff --git a/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneInventoryService.cs b/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneInventoryService.cs
deleted file mode 100644
index 54ba761..0000000
--- a/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneInventoryService.cs
+++ /dev/null
@@ -1,314 +0,0 @@
1/**
2 * Copyright (c) 2008, Contributors. All rights reserved.
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the Organizations nor the names of Individual
14 * Contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29using System;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33using log4net;
34using Nini.Config;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Framework.Communications;
38using OpenSim.Framework.Communications.Cache;
39using OpenSim.Framework.Servers;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42
43namespace OpenSim.Region.Environment.Modules.Hypergrid
44{
45 public class HGStandaloneInventoryService : IRegionModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private static bool initialized = false;
49 private static bool enabled = false;
50
51 Scene m_scene;
52 //InventoryService m_inventoryService;
53
54 #region IRegionModule interface
55
56 public void Initialise(Scene scene, IConfigSource config)
57 {
58 if (!initialized)
59 {
60 initialized = true;
61 m_scene = scene;
62
63 // This module is only on for standalones
64 enabled = !config.Configs["Startup"].GetBoolean("gridmode", true) && config.Configs["Startup"].GetBoolean("hypergrid", false);
65 }
66 }
67
68 public void PostInitialise()
69 {
70 if (enabled)
71 {
72 m_log.Info("[HGStandaloneInvService]: Starting...");
73 //m_inventoryService = new InventoryService(m_scene);
74 new InventoryService(m_scene);
75 }
76 }
77
78 public void Close()
79 {
80 }
81
82 public string Name
83 {
84 get { return "HGStandaloneInventoryService"; }
85 }
86
87 public bool IsSharedModule
88 {
89 get { return true; }
90 }
91
92 #endregion
93 }
94
95 public class InventoryService
96 {
97 private static readonly ILog m_log
98 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
99
100 private InventoryServiceBase m_inventoryService;
101 private IUserService m_userService;
102 private bool m_doLookup = false;
103
104 public bool DoLookup
105 {
106 get { return m_doLookup; }
107 set { m_doLookup = value; }
108 }
109
110 public InventoryService(Scene m_scene)
111 {
112 m_inventoryService = (InventoryServiceBase)m_scene.CommsManager.SecureInventoryService;
113 m_userService = m_scene.CommsManager.UserService;
114 AddHttpHandlers(m_scene);
115 }
116
117 protected void AddHttpHandlers(Scene m_scene)
118 {
119 BaseHttpServer httpServer = m_scene.CommsManager.HttpServer;
120
121 httpServer.AddStreamHandler(
122 new RestDeserialiseSecureHandler<Guid, InventoryCollection>(
123 "POST", "/GetInventory/", GetUserInventory, CheckAuthSession));
124
125 httpServer.AddStreamHandler(
126 new RestDeserialiseSecureHandler<InventoryFolderBase, bool>(
127 "POST", "/NewFolder/", m_inventoryService.AddFolder, CheckAuthSession));
128
129 httpServer.AddStreamHandler(
130 new RestDeserialiseSecureHandler<InventoryFolderBase, bool>(
131 "POST", "/UpdateFolder/", m_inventoryService.UpdateFolder, CheckAuthSession));
132
133 httpServer.AddStreamHandler(
134 new RestDeserialiseSecureHandler<InventoryFolderBase, bool>(
135 "POST", "/MoveFolder/", m_inventoryService.MoveFolder, CheckAuthSession));
136
137 httpServer.AddStreamHandler(
138 new RestDeserialiseSecureHandler<InventoryFolderBase, bool>(
139 "POST", "/PurgeFolder/", m_inventoryService.PurgeFolder, CheckAuthSession));
140
141 httpServer.AddStreamHandler(
142 new RestDeserialiseSecureHandler<InventoryItemBase, bool>(
143 "POST", "/NewItem/", m_inventoryService.AddItem, CheckAuthSession));
144
145 httpServer.AddStreamHandler(
146 new RestDeserialiseSecureHandler<InventoryItemBase, bool>(
147 "POST", "/DeleteItem/", m_inventoryService.DeleteItem, CheckAuthSession));
148
149 //// WARNING: Root folders no longer just delivers the root and immediate child folders (e.g
150 //// system folders such as Objects, Textures), but it now returns the entire inventory skeleton.
151 //// It would have been better to rename this request, but complexities in the BaseHttpServer
152 //// (e.g. any http request not found is automatically treated as an xmlrpc request) make it easier
153 //// to do this for now.
154 //m_scene.AddStreamHandler(
155 // new RestDeserialiseTrustedHandler<Guid, List<InventoryFolderBase>>
156 // ("POST", "/RootFolders/", GetInventorySkeleton, CheckTrustSource));
157
158 //// for persistent active gestures
159 //m_scene.AddStreamHandler(
160 // new RestDeserialiseTrustedHandler<Guid, List<InventoryItemBase>>
161 // ("POST", "/ActiveGestures/", GetActiveGestures, CheckTrustSource));
162 }
163
164
165 ///// <summary>
166 ///// Check that the source of an inventory request is one that we trust.
167 ///// </summary>
168 ///// <param name="peer"></param>
169 ///// <returns></returns>
170 //public bool CheckTrustSource(IPEndPoint peer)
171 //{
172 // if (m_doLookup)
173 // {
174 // m_log.InfoFormat("[GRID AGENT INVENTORY]: Checking trusted source {0}", peer);
175 // UriBuilder ub = new UriBuilder(m_userserver_url);
176 // IPAddress[] uaddrs = Dns.GetHostAddresses(ub.Host);
177 // foreach (IPAddress uaddr in uaddrs)
178 // {
179 // if (uaddr.Equals(peer.Address))
180 // {
181 // return true;
182 // }
183 // }
184
185 // m_log.WarnFormat(
186 // "[GRID AGENT INVENTORY]: Rejecting request since source {0} was not in the list of trusted sources",
187 // peer);
188
189 // return false;
190 // }
191 // else
192 // {
193 // return true;
194 // }
195 //}
196
197 /// <summary>
198 /// Check that the source of an inventory request for a particular agent is a current session belonging to
199 /// that agent.
200 /// </summary>
201 /// <param name="session_id"></param>
202 /// <param name="avatar_id"></param>
203 /// <returns></returns>
204 public bool CheckAuthSession(string session_id, string avatar_id)
205 {
206 if (m_doLookup)
207 {
208 m_log.InfoFormat("[HGStandaloneInvService]: checking authed session {0} {1}", session_id, avatar_id);
209 UUID userID = UUID.Zero;
210 UUID sessionID = UUID.Zero;
211 UUID.TryParse(avatar_id, out userID);
212 UUID.TryParse(session_id, out sessionID);
213 if (userID.Equals(UUID.Zero) || sessionID.Equals(UUID.Zero))
214 {
215 m_log.Info("[HGStandaloneInvService]: Invalid user or session id " + avatar_id + "; " + session_id);
216 return false;
217 }
218 UserProfileData userProfile = m_userService.GetUserProfile(userID);
219 if (userProfile != null && userProfile.CurrentAgent != null &&
220 userProfile.CurrentAgent.SessionID == sessionID)
221 {
222 m_log.Info("[HGStandaloneInvService]: user is logged in and session is valid. Authorizing access.");
223 return true;
224 }
225
226 m_log.Warn("[HGStandaloneInvService]: unknown user or session_id, request rejected");
227 return false;
228 }
229 else
230 {
231 return true;
232 }
233 }
234
235
236 /// <summary>
237 /// Return a user's entire inventory
238 /// </summary>
239 /// <param name="rawUserID"></param>
240 /// <returns>The user's inventory. If an inventory cannot be found then an empty collection is returned.</returns>
241 public InventoryCollection GetUserInventory(Guid rawUserID)
242 {
243 UUID userID = new UUID(rawUserID);
244
245 m_log.Info("[HGStandaloneInvService]: Processing request for inventory of " + userID);
246
247 // Uncomment me to simulate a slow responding inventory server
248 //Thread.Sleep(16000);
249
250 InventoryCollection invCollection = new InventoryCollection();
251
252 List<InventoryFolderBase> allFolders = ((InventoryServiceBase)m_inventoryService).GetInventorySkeleton(userID);
253
254 if (null == allFolders)
255 {
256 m_log.WarnFormat("[HGStandaloneInvService]: No inventory found for user {0}", rawUserID);
257
258 return invCollection;
259 }
260
261 List<InventoryItemBase> allItems = new List<InventoryItemBase>();
262
263 foreach (InventoryFolderBase folder in allFolders)
264 {
265 List<InventoryItemBase> items = ((InventoryServiceBase)m_inventoryService).RequestFolderItems(folder.ID);
266
267 if (items != null)
268 {
269 allItems.InsertRange(0, items);
270 }
271 }
272
273 invCollection.UserID = userID;
274 invCollection.Folders = allFolders;
275 invCollection.Items = allItems;
276
277 // foreach (InventoryFolderBase folder in invCollection.Folders)
278 // {
279 // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back folder {0} {1}", folder.Name, folder.ID);
280 // }
281 //
282 // foreach (InventoryItemBase item in invCollection.Items)
283 // {
284 // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back item {0} {1}, folder {2}", item.Name, item.ID, item.Folder);
285 // }
286
287 m_log.InfoFormat(
288 "[HGStandaloneInvService]: Sending back inventory response to user {0} containing {1} folders and {2} items",
289 invCollection.UserID, invCollection.Folders.Count, invCollection.Items.Count);
290
291 return invCollection;
292 }
293
294 /// <summary>
295 /// Guid to UUID wrapper for same name IInventoryServices method
296 /// </summary>
297 /// <param name="rawUserID"></param>
298 /// <returns></returns>
299 public List<InventoryFolderBase> GetInventorySkeleton(Guid rawUserID)
300 {
301 UUID userID = new UUID(rawUserID);
302 return ((InventoryServiceBase)m_inventoryService).GetInventorySkeleton(userID);
303 }
304
305 public List<InventoryItemBase> GetActiveGestures(Guid rawUserID)
306 {
307 UUID userID = new UUID(rawUserID);
308
309 m_log.InfoFormat("[HGStandaloneInvService]: fetching active gestures for user {0}", userID);
310
311 return ((InventoryServiceBase)m_inventoryService).GetActiveGestures(userID);
312 }
313 }
314}
diff --git a/OpenSim/Region/Environment/Modules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/Environment/Modules/Hypergrid/HGWorldMapModule.cs
deleted file mode 100644
index 1d9182e..0000000
--- a/OpenSim/Region/Environment/Modules/Hypergrid/HGWorldMapModule.cs
+++ /dev/null
@@ -1,178 +0,0 @@
1/**
2 * Copyright (c) 2008, Contributors. All rights reserved.
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the Organizations nor the names of Individual
14 * Contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29
30using System;
31using System.Collections;
32using System.Collections.Generic;
33using System.Drawing;
34using System.Drawing.Imaging;
35using System.IO;
36using System.Net;
37using System.Reflection;
38using System.Threading;
39using OpenMetaverse;
40using OpenMetaverse.Imaging;
41using OpenMetaverse.StructuredData;
42using log4net;
43using Nini.Config;
44using Nwc.XmlRpc;
45
46using OpenSim.Framework;
47using OpenSim.Framework.Communications.Cache;
48using OpenSim.Framework.Communications.Capabilities;
49using OpenSim.Framework.Servers;
50using OpenSim.Region.Framework.Interfaces;
51using OpenSim.Region.Framework.Scenes;
52using OpenSim.Region.Framework.Scenes.Types;
53using OpenSim.Region.Environment.Modules.World.WorldMap;
54using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
55
56using OSD = OpenMetaverse.StructuredData.OSD;
57using OSDMap = OpenMetaverse.StructuredData.OSDMap;
58using OSDArray = OpenMetaverse.StructuredData.OSDArray;
59
60namespace OpenSim.Region.Environment.Modules.Hypergrid
61{
62 public class HGWorldMapModule : WorldMapModule, IRegionModule
63 {
64 private static readonly ILog m_log =
65 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
66
67 #region IRegionModule Members
68
69 public override void Initialise(Scene scene, IConfigSource config)
70 {
71 IConfig startupConfig = config.Configs["Startup"];
72 if (startupConfig.GetString("WorldMapModule", "WorldMap") == "HGWorldMap")
73 m_Enabled = true;
74
75 if (!m_Enabled)
76 return;
77 m_log.Info("[HGMap] Initializing...");
78 m_scene = scene;
79 }
80
81
82 public override string Name
83 {
84 get { return "HGWorldMap"; }
85 }
86
87
88 #endregion
89
90 /// <summary>
91 /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
92 /// </summary>
93 /// <param name="minX"></param>
94 /// <param name="minY"></param>
95 /// <param name="maxX"></param>
96 /// <param name="maxY"></param>
97 public override void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
98 {
99 //
100 // WARNING!!! COPY & PASTE FROM SUPERCLASS
101 // The only difference is at the very end
102 //
103
104 m_log.Info("[HGMap]: Request map blocks " + minX + "-" + maxX + " " + minY + "-" + maxY);
105
106 //m_scene.ForEachScenePresence(delegate (ScenePresence sp) {
107 // if (!sp.IsChildAgent && sp.UUID == remoteClient.AgentId)
108 // {
109 // Console.WriteLine("XXX Root agent");
110 // DoRequestMapBlocks(remoteClient, minX, minY, maxX, maxY, flag);
111 // }
112 //};
113
114 List<MapBlockData> mapBlocks;
115 if ((flag & 0x10000) != 0) // user clicked on the map a tile that isn't visible
116 {
117 List<MapBlockData> response = new List<MapBlockData>();
118
119 // this should return one mapblock at most. But make sure: Look whether the one we requested is in there
120 mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY);
121 if (mapBlocks != null)
122 {
123 foreach (MapBlockData block in mapBlocks)
124 {
125 if (block.X == minX && block.Y == minY)
126 {
127 // found it => add it to response
128 response.Add(block);
129 break;
130 }
131 }
132 }
133 response = mapBlocks;
134 if (response.Count == 0)
135 {
136 // response still empty => couldn't find the map-tile the user clicked on => tell the client
137 MapBlockData block = new MapBlockData();
138 block.X = (ushort)minX;
139 block.Y = (ushort)minY;
140 block.Access = 254; // == not there
141 response.Add(block);
142 }
143 remoteClient.SendMapBlock(response, 0);
144 }
145 else
146 {
147 // normal mapblock request. Use the provided values
148 mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, maxX + 4, maxY + 4);
149
150 // Different from super
151 FillInMap(mapBlocks, minX, minY, maxX, maxY);
152 //
153
154 remoteClient.SendMapBlock(mapBlocks, flag);
155 }
156 }
157
158
159 private void FillInMap(List<MapBlockData> mapBlocks, int minX, int minY, int maxX, int maxY)
160 {
161 for (int x = minX; x <= maxX; x++)
162 for (int y = minY; y <= maxY; y++)
163 {
164 MapBlockData mblock = mapBlocks.Find(delegate(MapBlockData mb) { return ((mb.X == x) && (mb.Y == y)); });
165 if (mblock == null)
166 {
167 mblock = new MapBlockData();
168 mblock.X = (ushort)x;
169 mblock.Y = (ushort)y;
170 mblock.Name = "";
171 mblock.Access = 254; // not here???
172 mblock.MapImageId = UUID.Zero;
173 mapBlocks.Add(mblock);
174 }
175 }
176 }
177 }
178}
diff --git a/OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs
deleted file mode 100644
index 12a76de8..0000000
--- a/OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs
+++ /dev/null
@@ -1,1273 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Net;
32using System.Net.Security;
33using System.Security.Cryptography.X509Certificates;
34using System.Reflection;
35using System.Threading;
36using System.Web;
37
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40using OpenMetaverse.Packets;
41
42using log4net;
43using Nini.Config;
44using OpenSim.Framework;
45using OpenSim.Framework.Communications.Capabilities;
46using OpenSim.Framework.Servers;
47using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes;
49
50using OSD = OpenMetaverse.StructuredData.OSD;
51using OSDMap = OpenMetaverse.StructuredData.OSDMap;
52using OSDArray = OpenMetaverse.StructuredData.OSDArray;
53
54namespace OpenSim.Region.Environment.Modules.InterGrid
55{
56 public struct OGPState
57 {
58 public string first_name;
59 public string last_name;
60 public UUID agent_id;
61 public UUID local_agent_id;
62 public UUID region_id;
63 public uint circuit_code;
64 public UUID secure_session_id;
65 public UUID session_id;
66 public bool agent_access;
67 public string sim_access;
68 public uint god_level;
69 public bool god_overide;
70 public bool identified;
71 public bool transacted;
72 public bool age_verified;
73 public bool allow_redirect;
74 public int limited_to_estate;
75 public string inventory_host;
76 public bool src_can_see_mainland;
77 public int src_estate_id;
78 public int src_version;
79 public int src_parent_estate_id;
80 public bool visible_to_parent;
81 public string teleported_into_region;
82 }
83
84 public class OpenGridProtocolModule : IRegionModule
85 {
86 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
87 private List<Scene> m_scene = new List<Scene>();
88
89 private Dictionary<string, AgentCircuitData> CapsLoginID = new Dictionary<string, AgentCircuitData>();
90 private Dictionary<UUID, OGPState> m_OGPState = new Dictionary<UUID, OGPState>();
91 private Dictionary<string, string> m_loginToRegionState = new Dictionary<string, string>();
92
93
94 private string LastNameSuffix = "_EXTERNAL";
95 private string FirstNamePrefix = "";
96 private string httpsCN = "";
97 private bool httpSSL = false;
98 private uint httpsslport = 0;
99 private bool GridMode = false;
100
101 #region IRegionModule Members
102
103 public void Initialise(Scene scene, IConfigSource config)
104 {
105 bool enabled = false;
106 IConfig cfg = null;
107 IConfig httpcfg = null;
108 IConfig startupcfg = null;
109 try
110 {
111 cfg = config.Configs["OpenGridProtocol"];
112 } catch (NullReferenceException)
113 {
114 enabled = false;
115 }
116
117 try
118 {
119 httpcfg = config.Configs["Network"];
120 }
121 catch (NullReferenceException)
122 {
123
124 }
125 try
126 {
127 startupcfg = config.Configs["Startup"];
128 }
129 catch (NullReferenceException)
130 {
131
132 }
133
134 if (startupcfg != null)
135 {
136 GridMode = enabled = startupcfg.GetBoolean("gridmode", false);
137 }
138
139 if (cfg != null)
140 {
141 enabled = cfg.GetBoolean("ogp_enabled", false);
142 LastNameSuffix = cfg.GetString("ogp_lastname_suffix", "_EXTERNAL");
143 FirstNamePrefix = cfg.GetString("ogp_firstname_prefix", "");
144 if (enabled)
145 {
146 m_log.Warn("[OGP]: Open Grid Protocol is on, Listening for Clients on /agent/");
147 lock (m_scene)
148 {
149 if (m_scene.Count == 0)
150 {
151 scene.CommsManager.HttpServer.AddLLSDHandler("/agent/", ProcessAgentDomainMessage);
152 scene.CommsManager.HttpServer.AddLLSDHandler("/", ProcessRegionDomainSeed);
153 try
154 {
155 ServicePointManager.ServerCertificateValidationCallback += customXertificateValidation;
156 }
157 catch (NotImplementedException)
158 {
159 try
160 {
161#pragma warning disable 0612, 0618
162 // Mono does not implement the ServicePointManager.ServerCertificateValidationCallback yet! Don't remove this!
163 ServicePointManager.CertificatePolicy = new MonoCert();
164#pragma warning restore 0612, 0618
165 }
166 catch (Exception)
167 {
168 m_log.Error("[OGP]: Certificate validation handler change not supported. You may get ssl certificate validation errors teleporting from your region to some SSL regions.");
169 }
170 }
171
172 }
173 // can't pick the region 'agent' because it would conflict with our agent domain handler
174 // a zero length region name would conflict with are base region seed cap
175 if (!SceneListDuplicateCheck(scene.RegionInfo.RegionName) && scene.RegionInfo.RegionName.ToLower() != "agent" && scene.RegionInfo.RegionName.Length > 0)
176 {
177 scene.CommsManager.HttpServer.AddLLSDHandler(
178 "/" + HttpUtility.UrlPathEncode(scene.RegionInfo.RegionName.ToLower()),
179 ProcessRegionDomainSeed);
180 }
181
182 if (!m_scene.Contains(scene))
183 m_scene.Add(scene);
184 }
185 }
186 }
187 lock (m_scene)
188 {
189 if (m_scene.Count == 1)
190 {
191 if (httpcfg != null)
192 {
193 httpSSL = httpcfg.GetBoolean("http_listener_ssl", false);
194 httpsCN = httpcfg.GetString("http_listener_cn", scene.RegionInfo.ExternalHostName);
195 if (httpsCN.Length == 0)
196 httpsCN = scene.RegionInfo.ExternalHostName;
197 httpsslport = (uint)httpcfg.GetInt("http_listener_sslport",((int)scene.RegionInfo.HttpPort + 1));
198 }
199 }
200 }
201 }
202
203 public void PostInitialise()
204 {
205 }
206
207 public void Close()
208 {
209 //scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel;
210 }
211
212 public string Name
213 {
214 get { return "OpenGridProtocolModule"; }
215 }
216
217 public bool IsSharedModule
218 {
219 get { return true; }
220 }
221
222 #endregion
223
224 public OSD ProcessRegionDomainSeed(string path, OSD request, string endpoint)
225 {
226 string[] pathSegments = path.Split('/');
227
228 if (pathSegments.Length <= 1)
229 {
230 return GenerateNoHandlerMessage();
231
232 }
233
234 return GenerateRezAvatarRequestMessage(pathSegments[1]);
235
236
237
238 //m_log.InfoFormat("[OGP]: path {0}, segments {1} segment[1] {2} Last segment {3}",
239 // path, pathSegments.Length, pathSegments[1], pathSegments[pathSegments.Length - 1]);
240 //return new OSDMap();
241
242 }
243
244 public OSD ProcessAgentDomainMessage(string path, OSD request, string endpoint)
245 {
246 // /agent/*
247
248 string[] pathSegments = path.Split('/');
249 if (pathSegments.Length <= 1)
250 {
251 return GenerateNoHandlerMessage();
252
253 }
254 if (pathSegments[0].Length == 0 && pathSegments[1].Length == 0)
255 {
256 return GenerateRezAvatarRequestMessage("");
257 }
258 m_log.InfoFormat("[OGP]: path {0}, segments {1} segment[1] {2} Last segment {3}",
259 path, pathSegments.Length, pathSegments[1], pathSegments[pathSegments.Length - 1]);
260
261 switch (pathSegments[pathSegments.Length - 1])
262 {
263 case "rez_avatar":
264 return RezAvatarMethod(path, request);
265 //break;
266 case "derez_avatar":
267 return DerezAvatarMethod(path, request);
268 //break;
269
270 }
271 if (path.Length < 2)
272 {
273 return GenerateNoHandlerMessage();
274 }
275
276 switch (pathSegments[pathSegments.Length - 2] + "/" + pathSegments[pathSegments.Length - 1])
277 {
278 case "rez_avatar/rez":
279 return RezAvatarMethod(path, request);
280 //break;
281 case "rez_avatar/request":
282 return RequestRezAvatarMethod(path, request);
283 case "rez_avatar/place":
284 return RequestRezAvatarMethod(path, request);
285 case "rez_avatar/derez":
286 return DerezAvatarMethod(path, request);
287 //break;
288 default:
289 return GenerateNoHandlerMessage();
290 }
291 //return null;
292 }
293
294 private OSD GenerateRezAvatarRequestMessage(string regionname)
295 {
296 Scene region = null;
297 bool usedroot = false;
298
299 if (regionname.Length == 0)
300 {
301 region = GetRootScene();
302 usedroot = true;
303 }
304 else
305 {
306 region = GetScene(HttpUtility.UrlDecode(regionname).ToLower());
307 }
308
309 // this shouldn't happen since we don't listen for a region that is down.. but
310 // it might if the region was taken down or is in the middle of restarting
311
312 if (region == null)
313 {
314 region = GetRootScene();
315 usedroot = true;
316 }
317
318 UUID statekeeper = UUID.Random();
319
320
321
322
323 RegionInfo reg = region.RegionInfo;
324
325 OSDMap responseMap = new OSDMap();
326 string rezHttpProtocol = "http://";
327 //string regionCapsHttpProtocol = "http://";
328 string httpaddr = reg.ExternalHostName;
329 string urlport = reg.HttpPort.ToString();
330 string requestpath = "/agent/" + statekeeper + "/rez_avatar/request";
331
332 if (!usedroot)
333 {
334 lock (m_loginToRegionState)
335 {
336 if (!m_loginToRegionState.ContainsKey(requestpath))
337 {
338 m_loginToRegionState.Add(requestpath, region.RegionInfo.RegionName.ToLower());
339 }
340 }
341 }
342
343 if (httpSSL)
344 {
345 rezHttpProtocol = "https://";
346 //regionCapsHttpProtocol = "https://";
347 urlport = httpsslport.ToString();
348
349 if (httpsCN.Length > 0)
350 httpaddr = httpsCN;
351 }
352
353 responseMap["connect"] = OSD.FromBoolean(true);
354 OSDMap capabilitiesMap = new OSDMap();
355 capabilitiesMap["rez_avatar/request"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + requestpath);
356 responseMap["capabilities"] = capabilitiesMap;
357
358 return responseMap;
359 }
360
361 // Using OpenSim.Framework.Communications.Capabilities.Caps here one time..
362 // so the long name is probably better then a using statement
363 public void OnRegisterCaps(UUID agentID, OpenSim.Framework.Communications.Capabilities.Caps caps)
364 {
365 /* If we ever want to register our own caps here....
366 *
367 string capsBase = "/CAPS/" + caps.CapsObjectPath;
368 caps.RegisterHandler("CAPNAME",
369 new RestStreamHandler("POST", capsBase + CAPSPOSTFIX!,
370 delegate(string request, string path, string param,
371 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
372 {
373 return METHODHANDLER(request, path, param,
374 agentID, caps);
375 }));
376
377 *
378 */
379 }
380
381 public OSD RequestRezAvatarMethod(string path, OSD request)
382 {
383 //System.Console.WriteLine("[REQUESTREZAVATAR]: " + request.ToString());
384
385 OSDMap requestMap = (OSDMap)request;
386
387
388 Scene homeScene = null;
389
390 lock (m_loginToRegionState)
391 {
392 if (m_loginToRegionState.ContainsKey(path))
393 {
394 homeScene = GetScene(m_loginToRegionState[path]);
395 m_loginToRegionState.Remove(path);
396
397 if (homeScene == null)
398 homeScene = GetRootScene();
399 }
400 else
401 {
402 homeScene = GetRootScene();
403 }
404 }
405
406 // Homescene is still null, we must have no regions that are up
407 if (homeScene == null)
408 return GenerateNoHandlerMessage();
409
410 RegionInfo reg = homeScene.RegionInfo;
411 ulong regionhandle = GetOSCompatibleRegionHandle(reg);
412 //string RegionURI = reg.ServerURI;
413 //int RegionPort = (int)reg.HttpPort;
414
415 UUID RemoteAgentID = requestMap["agent_id"].AsUUID();
416
417 // will be used in the future. The client always connects with the aditi agentid currently
418 UUID LocalAgentID = RemoteAgentID;
419
420 string FirstName = requestMap["first_name"].AsString();
421 string LastName = requestMap["last_name"].AsString();
422
423 FirstName = FirstNamePrefix + FirstName;
424 LastName = LastName + LastNameSuffix;
425
426 OGPState userState = GetOGPState(LocalAgentID);
427
428 userState.first_name = requestMap["first_name"].AsString();
429 userState.last_name = requestMap["last_name"].AsString();
430 userState.age_verified = requestMap["age_verified"].AsBoolean();
431 userState.transacted = requestMap["transacted"].AsBoolean();
432 userState.agent_access = requestMap["agent_access"].AsBoolean();
433 userState.allow_redirect = requestMap["allow_redirect"].AsBoolean();
434 userState.identified = requestMap["identified"].AsBoolean();
435 userState.god_level = (uint)requestMap["god_level"].AsInteger();
436 userState.sim_access = requestMap["sim_access"].AsString();
437 userState.agent_id = RemoteAgentID;
438 userState.limited_to_estate = requestMap["limited_to_estate"].AsInteger();
439 userState.src_can_see_mainland = requestMap["src_can_see_mainland"].AsBoolean();
440 userState.src_estate_id = requestMap["src_estate_id"].AsInteger();
441 userState.local_agent_id = LocalAgentID;
442 userState.teleported_into_region = reg.RegionName.ToLower();
443
444 UpdateOGPState(LocalAgentID, userState);
445
446 OSDMap responseMap = new OSDMap();
447
448 if (RemoteAgentID == UUID.Zero)
449 {
450 responseMap["connect"] = OSD.FromBoolean(false);
451 responseMap["message"] = OSD.FromString("No agent ID was specified in rez_avatar/request");
452 m_log.Error("[OGP]: rez_avatar/request failed because no avatar UUID was provided in the request body");
453 return responseMap;
454 }
455
456 responseMap["sim_host"] = OSD.FromString(reg.ExternalHostName);
457
458 // DEPRECIATED
459 responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString());
460
461 responseMap["connect"] = OSD.FromBoolean(true);
462 responseMap["sim_port"] = OSD.FromInteger(reg.InternalEndPoint.Port);
463 responseMap["region_x"] = OSD.FromInteger(reg.RegionLocX * (uint)Constants.RegionSize); // LLX
464 responseMap["region_y"] = OSD.FromInteger(reg.RegionLocY * (uint)Constants.RegionSize); // LLY
465 responseMap["region_id"] = OSD.FromUUID(reg.originRegionID);
466 responseMap["sim_access"] = OSD.FromString((reg.RegionSettings.Maturity == 1) ? "Mature" : "PG");
467
468 // Generate a dummy agent for the user so we can get back a CAPS path
469 AgentCircuitData agentData = new AgentCircuitData();
470 agentData.AgentID = LocalAgentID;
471 agentData.BaseFolder = UUID.Zero;
472 agentData.CapsPath = CapsUtil.GetRandomCapsObjectPath();
473 agentData.child = false;
474 agentData.circuitcode = (uint)(Util.RandomClass.Next());
475 agentData.firstname = FirstName;
476 agentData.lastname = LastName;
477 agentData.SecureSessionID = UUID.Random();
478 agentData.SessionID = UUID.Random();
479 agentData.startpos = new Vector3(128f, 128f, 100f);
480
481 // Pre-Fill our region cache with information on the agent.
482 UserAgentData useragent = new UserAgentData();
483 useragent.AgentIP = "unknown";
484 useragent.AgentOnline = true;
485 useragent.AgentPort = (uint)0;
486 useragent.Handle = regionhandle;
487 useragent.InitialRegion = reg.originRegionID;
488 useragent.LoginTime = Util.UnixTimeSinceEpoch();
489 useragent.LogoutTime = 0;
490 useragent.Position = agentData.startpos;
491 useragent.Region = reg.originRegionID;
492 useragent.SecureSessionID = agentData.SecureSessionID;
493 useragent.SessionID = agentData.SessionID;
494
495 UserProfileData userProfile = new UserProfileData();
496 userProfile.AboutText = "OGP User";
497 userProfile.CanDoMask = (uint)0;
498 userProfile.Created = Util.UnixTimeSinceEpoch();
499 userProfile.CurrentAgent = useragent;
500 userProfile.CustomType = "OGP";
501 userProfile.FirstLifeAboutText = "I'm testing OpenGrid Protocol";
502 userProfile.FirstLifeImage = UUID.Zero;
503 userProfile.FirstName = agentData.firstname;
504 userProfile.GodLevel = 0;
505 userProfile.HomeLocation = agentData.startpos;
506 userProfile.HomeLocationX = agentData.startpos.X;
507 userProfile.HomeLocationY = agentData.startpos.Y;
508 userProfile.HomeLocationZ = agentData.startpos.Z;
509 userProfile.HomeLookAt = Vector3.Zero;
510 userProfile.HomeLookAtX = userProfile.HomeLookAt.X;
511 userProfile.HomeLookAtY = userProfile.HomeLookAt.Y;
512 userProfile.HomeLookAtZ = userProfile.HomeLookAt.Z;
513 userProfile.HomeRegion = reg.RegionHandle;
514 userProfile.HomeRegionID = reg.originRegionID;
515 userProfile.HomeRegionX = reg.RegionLocX;
516 userProfile.HomeRegionY = reg.RegionLocY;
517 userProfile.ID = agentData.AgentID;
518 userProfile.Image = UUID.Zero;
519 userProfile.LastLogin = Util.UnixTimeSinceEpoch();
520 userProfile.Partner = UUID.Zero;
521 userProfile.PasswordHash = "$1$";
522 userProfile.PasswordSalt = "";
523 userProfile.RootInventoryFolderID = UUID.Zero;
524 userProfile.SurName = agentData.lastname;
525 userProfile.UserAssetURI = homeScene.CommsManager.NetworkServersInfo.AssetURL;
526 userProfile.UserFlags = 0;
527 userProfile.UserInventoryURI = homeScene.CommsManager.NetworkServersInfo.InventoryURL;
528 userProfile.WantDoMask = 0;
529 userProfile.WebLoginKey = UUID.Random();
530
531 // Do caps registration
532 // get seed capagentData.firstname = FirstName;agentData.lastname = LastName;
533 if (homeScene.CommsManager.UserService.GetUserProfile(agentData.AgentID) == null && !GridMode)
534 {
535 homeScene.CommsManager.UserAdminService.AddUser(
536 agentData.firstname, agentData.lastname, CreateRandomStr(7), "",
537 homeScene.RegionInfo.RegionLocX, homeScene.RegionInfo.RegionLocY, agentData.AgentID);
538
539 UserProfileData userProfile2 = homeScene.CommsManager.UserService.GetUserProfile(agentData.AgentID);
540 if (userProfile2 != null)
541 {
542 userProfile = userProfile2;
543 userProfile.AboutText = "OGP USER";
544 userProfile.FirstLifeAboutText = "OGP USER";
545 homeScene.CommsManager.UserService.UpdateUserProfile(userProfile);
546 }
547 }
548
549 // Stick our data in the cache so the region will know something about us
550 homeScene.CommsManager.UserProfileCacheService.PreloadUserCache(agentData.AgentID, userProfile);
551
552 // Call 'new user' event handler
553 homeScene.NewUserConnection(agentData);
554
555 //string raCap = string.Empty;
556
557 UUID AvatarRezCapUUID = LocalAgentID;
558 string rezAvatarPath = "/agent/" + AvatarRezCapUUID + "/rez_avatar/rez";
559 string derezAvatarPath = "/agent/" + AvatarRezCapUUID + "/rez_avatar/derez";
560 // Get a reference to the user's cap so we can pull out the Caps Object Path
561 OpenSim.Framework.Communications.Capabilities.Caps userCap
562 = homeScene.CapsModule.GetCapsHandlerForUser(agentData.AgentID);
563
564 string rezHttpProtocol = "http://";
565 string regionCapsHttpProtocol = "http://";
566 string httpaddr = reg.ExternalHostName;
567 string urlport = reg.HttpPort.ToString();
568
569 if (httpSSL)
570 {
571 rezHttpProtocol = "https://";
572 regionCapsHttpProtocol = "https://";
573 urlport = httpsslport.ToString();
574
575 if (httpsCN.Length > 0)
576 httpaddr = httpsCN;
577 }
578
579 // DEPRECIATED
580 responseMap["seed_capability"]
581 = OSD.FromString(
582 regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath));
583
584 // REPLACEMENT
585 responseMap["region_seed_capability"]
586 = OSD.FromString(
587 regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath));
588
589 responseMap["rez_avatar"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath);
590 responseMap["rez_avatar/rez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath);
591 responseMap["rez_avatar/derez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + derezAvatarPath);
592
593 // Add the user to the list of CAPS that are outstanding.
594 // well allow the caps hosts in this dictionary
595 lock (CapsLoginID)
596 {
597 if (CapsLoginID.ContainsKey(rezAvatarPath))
598 {
599 CapsLoginID[rezAvatarPath] = agentData;
600
601 // This is a joke, if you didn't notice... It's so unlikely to happen, that I'll print this message if it does occur!
602 m_log.Error("[OGP]: Holy anomoly batman! Caps path already existed! All the UUID Duplication worries were founded!");
603 }
604 else
605 {
606 CapsLoginID.Add(rezAvatarPath, agentData);
607 }
608 }
609
610 //System.Console.WriteLine("Response:" + responseMap.ToString());
611 return responseMap;
612 }
613
614 public OSD RezAvatarMethod(string path, OSD request)
615 {
616 m_log.WarnFormat("[REZAVATAR]: {0}", request.ToString());
617
618 OSDMap responseMap = new OSDMap();
619
620 AgentCircuitData userData = null;
621
622 // Only people we've issued a cap can go further
623 if (TryGetAgentCircuitData(path,out userData))
624 {
625 OSDMap requestMap = (OSDMap)request;
626
627 // take these values to start. There's a few more
628 UUID SecureSessionID=requestMap["secure_session_id"].AsUUID();
629 UUID SessionID = requestMap["session_id"].AsUUID();
630 int circuitcode = requestMap["circuit_code"].AsInteger();
631 OSDArray Parameter = new OSDArray();
632 if (requestMap.ContainsKey("parameter"))
633 {
634 Parameter = (OSDArray)requestMap["parameter"];
635 }
636
637 //int version = 1;
638 int estateID = 1;
639 int parentEstateID = 1;
640 UUID regionID = UUID.Zero;
641 bool visibleToParent = true;
642
643 for (int i = 0; i < Parameter.Count; i++)
644 {
645 OSDMap item = (OSDMap)Parameter[i];
646// if (item.ContainsKey("version"))
647// {
648// version = item["version"].AsInteger();
649// }
650 if (item.ContainsKey("estate_id"))
651 {
652 estateID = item["estate_id"].AsInteger();
653 }
654 if (item.ContainsKey("parent_estate_id"))
655 {
656 parentEstateID = item["parent_estate_id"].AsInteger();
657
658 }
659 if (item.ContainsKey("region_id"))
660 {
661 regionID = item["region_id"].AsUUID();
662
663 }
664 if (item.ContainsKey("visible_to_parent"))
665 {
666 visibleToParent = item["visible_to_parent"].AsBoolean();
667 }
668 }
669 //Update our Circuit data with the real values
670 userData.SecureSessionID = SecureSessionID;
671 userData.SessionID = SessionID;
672
673 OGPState userState = GetOGPState(userData.AgentID);
674
675 // Locate a home scene suitable for the user.
676 Scene homeScene = null;
677
678 homeScene = GetScene(userState.teleported_into_region);
679
680 if (homeScene == null)
681 homeScene = GetRootScene();
682
683 if (homeScene != null)
684 {
685 // Get a referenceokay - to their Cap object so we can pull out the capobjectroot
686 OpenSim.Framework.Communications.Capabilities.Caps userCap
687 = homeScene.CapsModule.GetCapsHandlerForUser(userData.AgentID);
688
689 //Update the circuit data in the region so this user is authorized
690 homeScene.UpdateCircuitData(userData);
691 homeScene.ChangeCircuitCode(userData.circuitcode,(uint)circuitcode);
692
693 // Load state
694
695
696 // Keep state changes
697 userState.first_name = requestMap["first_name"].AsString();
698 userState.secure_session_id = requestMap["secure_session_id"].AsUUID();
699 userState.age_verified = requestMap["age_verified"].AsBoolean();
700 userState.region_id = homeScene.RegionInfo.originRegionID; // replace 0000000 with our regionid
701 userState.transacted = requestMap["transacted"].AsBoolean();
702 userState.agent_access = requestMap["agent_access"].AsBoolean();
703 userState.inventory_host = requestMap["inventory_host"].AsString();
704 userState.identified = requestMap["identified"].AsBoolean();
705 userState.session_id = requestMap["session_id"].AsUUID();
706 userState.god_level = (uint)requestMap["god_level"].AsInteger();
707 userState.last_name = requestMap["last_name"].AsString();
708 userState.god_overide = requestMap["god_override"].AsBoolean();
709 userState.circuit_code = (uint)requestMap["circuit_code"].AsInteger();
710 userState.limited_to_estate = requestMap["limited_to_estate"].AsInteger();
711 userState.src_estate_id = estateID;
712 userState.region_id = regionID;
713 userState.src_parent_estate_id = parentEstateID;
714 userState.visible_to_parent = visibleToParent;
715
716 // Save state changes
717 UpdateOGPState(userData.AgentID, userState);
718
719 // Get the region information for the home region.
720 RegionInfo reg = homeScene.RegionInfo;
721
722 // Dummy positional and look at info.. we don't have it.
723 OSDArray PositionArray = new OSDArray();
724 PositionArray.Add(OSD.FromInteger(128));
725 PositionArray.Add(OSD.FromInteger(128));
726 PositionArray.Add(OSD.FromInteger(40));
727
728 OSDArray LookAtArray = new OSDArray();
729 LookAtArray.Add(OSD.FromInteger(1));
730 LookAtArray.Add(OSD.FromInteger(1));
731 LookAtArray.Add(OSD.FromInteger(1));
732
733 // Our region's X and Y position in OpenSimulator space.
734 uint fooX = reg.RegionLocX;
735 uint fooY = reg.RegionLocY;
736 m_log.InfoFormat("[OGP]: region x({0}) region y({1})", fooX, fooY);
737 m_log.InfoFormat("[OGP]: region http {0} {1}", reg.ServerURI, reg.HttpPort);
738 m_log.InfoFormat("[OGO]: region UUID {0} ", reg.RegionID);
739
740 // Convert the X and Y position to LL space
741 responseMap["region_x"] = OSD.FromInteger(fooX * (uint)Constants.RegionSize); // convert it to LL X
742 responseMap["region_y"] = OSD.FromInteger(fooY * (uint)Constants.RegionSize); // convert it to LL Y
743
744 // Give em a new seed capability
745 responseMap["seed_capability"] = OSD.FromString("http://" + reg.ExternalHostName + ":" + reg.HttpPort + "/CAPS/" + userCap.CapsObjectPath + "0000/");
746 responseMap["region"] = OSD.FromUUID(reg.originRegionID);
747 responseMap["look_at"] = LookAtArray;
748
749 responseMap["sim_port"] = OSD.FromInteger(reg.InternalEndPoint.Port);
750 responseMap["sim_host"] = OSD.FromString(reg.ExternalHostName);// + ":" + reg.InternalEndPoint.Port.ToString());
751
752 // DEPRECIATED
753 responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString());
754
755 responseMap["session_id"] = OSD.FromUUID(SessionID);
756 responseMap["secure_session_id"] = OSD.FromUUID(SecureSessionID);
757 responseMap["circuit_code"] = OSD.FromInteger(circuitcode);
758
759 responseMap["position"] = PositionArray;
760
761 responseMap["region_id"] = OSD.FromUUID(reg.originRegionID);
762
763 responseMap["sim_access"] = OSD.FromString("Mature");
764
765 responseMap["connect"] = OSD.FromBoolean(true);
766
767
768
769 m_log.InfoFormat("[OGP]: host: {0}, IP {1}", responseMap["sim_host"].ToString(), responseMap["sim_ip"].ToString());
770 }
771 }
772
773 return responseMap;
774 }
775
776 public OSD DerezAvatarMethod(string path, OSD request)
777 {
778 m_log.ErrorFormat("DerezPath: {0}, Request: {1}", path, request.ToString());
779
780 //LLSD llsdResponse = null;
781 OSDMap responseMap = new OSDMap();
782
783 string[] PathArray = path.Split('/');
784 m_log.InfoFormat("[OGP]: prefix {0}, uuid {1}, suffix {2}", PathArray[1], PathArray[2], PathArray[3]);
785 string uuidString = PathArray[2];
786 m_log.InfoFormat("[OGP]: Request to Derez avatar with UUID {0}", uuidString);
787 UUID userUUID = UUID.Zero;
788 if (UUID.TryParse(uuidString, out userUUID))
789 {
790 UUID RemoteID = (UUID)uuidString;
791 UUID LocalID = RemoteID;
792 // FIXME: TODO: Routine to map RemoteUUIDs to LocalUUIds
793 // would be done already.. but the client connects with the Aditi UUID
794 // regardless over the UDP stack
795
796 OGPState userState = GetOGPState(LocalID);
797 if (userState.agent_id != UUID.Zero)
798 {
799 //OSDMap outboundRequestMap = new OSDMap();
800 OSDMap inboundRequestMap = (OSDMap)request;
801 string rezAvatarString = inboundRequestMap["rez_avatar"].AsString();
802 if (rezAvatarString.Length == 0)
803 {
804 rezAvatarString = inboundRequestMap["rez_avatar/rez"].AsString();
805 }
806 OSDArray LookAtArray = new OSDArray();
807 LookAtArray.Add(OSD.FromInteger(1));
808 LookAtArray.Add(OSD.FromInteger(1));
809 LookAtArray.Add(OSD.FromInteger(1));
810
811 OSDArray PositionArray = new OSDArray();
812 PositionArray.Add(OSD.FromInteger(128));
813 PositionArray.Add(OSD.FromInteger(128));
814 PositionArray.Add(OSD.FromInteger(40));
815
816 OSDArray lookArray = new OSDArray();
817 lookArray.Add(OSD.FromInteger(128));
818 lookArray.Add(OSD.FromInteger(128));
819 lookArray.Add(OSD.FromInteger(40));
820
821 responseMap["connect"] = OSD.FromBoolean(true);// it's okay to give this user up
822 responseMap["look_at"] = LookAtArray;
823
824 m_log.WarnFormat("[OGP]: Invoking rez_avatar on host:{0} for avatar: {1} {2}", rezAvatarString, userState.first_name, userState.last_name);
825
826 OSDMap rezResponseMap = invokeRezAvatarCap(responseMap, rezAvatarString,userState);
827
828 // If invoking it returned an error, parse and end
829 if (rezResponseMap.ContainsKey("connect"))
830 {
831 if (rezResponseMap["connect"].AsBoolean() == false)
832 {
833 return responseMap;
834 }
835 }
836
837 string rezRespSeedCap = "";
838
839 // DEPRECIATED
840 if (rezResponseMap.ContainsKey("seed_capability"))
841 rezRespSeedCap = rezResponseMap["seed_capability"].AsString();
842
843 // REPLACEMENT
844 if (rezResponseMap.ContainsKey("region_seed_capability"))
845 rezRespSeedCap = rezResponseMap["region_seed_capability"].AsString();
846
847 // REPLACEMENT
848 if (rezResponseMap.ContainsKey("rez_avatar/rez"))
849 rezRespSeedCap = rezResponseMap["rez_avatar/rez"].AsString();
850
851 // DEPRECIATED
852 string rezRespSim_ip = rezResponseMap["sim_ip"].AsString();
853
854 string rezRespSim_host = rezResponseMap["sim_host"].AsString();
855
856 int rrPort = rezResponseMap["sim_port"].AsInteger();
857 int rrX = rezResponseMap["region_x"].AsInteger();
858 int rrY = rezResponseMap["region_y"].AsInteger();
859 m_log.ErrorFormat("X:{0}, Y:{1}", rrX, rrY);
860 UUID rrRID = rezResponseMap["region_id"].AsUUID();
861 OSDArray RezResponsePositionArray = null;
862 string rrAccess = rezResponseMap["sim_access"].AsString();
863 if (rezResponseMap.ContainsKey("position"))
864 {
865 RezResponsePositionArray = (OSDArray)rezResponseMap["position"];
866 }
867 // DEPRECIATED
868 responseMap["seed_capability"] = OSD.FromString(rezRespSeedCap);
869
870 // REPLACEMENT r3
871 responseMap["region_seed_capability"] = OSD.FromString(rezRespSeedCap);
872
873 // DEPRECIATED
874 responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(rezRespSim_ip).ToString());
875
876 responseMap["sim_host"] = OSD.FromString(rezRespSim_host);
877 responseMap["sim_port"] = OSD.FromInteger(rrPort);
878 responseMap["region_x"] = OSD.FromInteger(rrX );
879 responseMap["region_y"] = OSD.FromInteger(rrY );
880 responseMap["region_id"] = OSD.FromUUID(rrRID);
881 responseMap["sim_access"] = OSD.FromString(rrAccess);
882
883 if (RezResponsePositionArray != null)
884 {
885 responseMap["position"] = RezResponsePositionArray;
886 }
887 responseMap["look_at"] = lookArray;
888 responseMap["connect"] = OSD.FromBoolean(true);
889
890 ShutdownConnection(LocalID,this);
891 // PLEASE STOP CHANGING THIS TO an M_LOG, M_LOG DOESN'T WORK ON MULTILINE .TOSTRINGS
892 System.Console.WriteLine("RESPONSEDEREZ: " + responseMap.ToString());
893 return responseMap;
894 }
895 else
896 {
897 return GenerateNoStateMessage(LocalID);
898 }
899 }
900 else
901 {
902 return GenerateNoHandlerMessage();
903 }
904
905 //return responseMap;
906 }
907
908 private OSDMap invokeRezAvatarCap(OSDMap responseMap, string CapAddress, OGPState userState)
909 {
910 Scene reg = GetRootScene();
911
912 WebRequest DeRezRequest = WebRequest.Create(CapAddress);
913 DeRezRequest.Method = "POST";
914 DeRezRequest.ContentType = "application/xml+llsd";
915
916 OSDMap RAMap = new OSDMap();
917 OSDMap AgentParms = new OSDMap();
918 OSDMap RegionParms = new OSDMap();
919
920 OSDArray Parameter = new OSDArray(2);
921
922 OSDMap version = new OSDMap();
923 version["version"] = OSD.FromInteger(userState.src_version);
924 Parameter.Add(version);
925
926 OSDMap SrcData = new OSDMap();
927 SrcData["estate_id"] = OSD.FromInteger(reg.RegionInfo.EstateSettings.EstateID);
928 SrcData["parent_estate_id"] = OSD.FromInteger((reg.RegionInfo.EstateSettings.ParentEstateID == 100 ? 1 : reg.RegionInfo.EstateSettings.ParentEstateID));
929 SrcData["region_id"] = OSD.FromUUID(reg.RegionInfo.originRegionID);
930 SrcData["visible_to_parent"] = OSD.FromBoolean(userState.visible_to_parent);
931 Parameter.Add(SrcData);
932
933 AgentParms["first_name"] = OSD.FromString(userState.first_name);
934 AgentParms["last_name"] = OSD.FromString(userState.last_name);
935 AgentParms["agent_id"] = OSD.FromUUID(userState.agent_id);
936 RegionParms["region_id"] = OSD.FromUUID(userState.region_id);
937 AgentParms["circuit_code"] = OSD.FromInteger(userState.circuit_code);
938 AgentParms["secure_session_id"] = OSD.FromUUID(userState.secure_session_id);
939 AgentParms["session_id"] = OSD.FromUUID(userState.session_id);
940 AgentParms["agent_access"] = OSD.FromBoolean(userState.agent_access);
941 AgentParms["god_level"] = OSD.FromInteger(userState.god_level);
942 AgentParms["god_overide"] = OSD.FromBoolean(userState.god_overide);
943 AgentParms["identified"] = OSD.FromBoolean(userState.identified);
944 AgentParms["transacted"] = OSD.FromBoolean(userState.transacted);
945 AgentParms["age_verified"] = OSD.FromBoolean(userState.age_verified);
946 AgentParms["limited_to_estate"] = OSD.FromInteger(userState.limited_to_estate);
947 AgentParms["inventory_host"] = OSD.FromString(userState.inventory_host);
948
949 // version 1
950 RAMap = AgentParms;
951
952 // Planned for version 2
953 // RAMap["agent_params"] = AgentParms;
954
955 RAMap["region_params"] = RegionParms;
956 RAMap["parameter"] = Parameter;
957
958 string RAMapString = RAMap.ToString();
959 m_log.InfoFormat("[OGP] RAMap string {0}", RAMapString);
960 OSD LLSDofRAMap = RAMap; // RENAME if this works
961
962 m_log.InfoFormat("[OGP]: LLSD of map as string was {0}", LLSDofRAMap.ToString());
963 //m_log.InfoFormat("[OGP]: LLSD+XML: {0}", LLSDParser.SerializeXmlString(LLSDofRAMap));
964 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap);
965
966 //string bufferDump = System.Text.Encoding.ASCII.GetString(buffer);
967 //m_log.InfoFormat("[OGP]: buffer form is {0}",bufferDump);
968 //m_log.InfoFormat("[OGP]: LLSD of map was {0}",buffer.Length);
969
970 Stream os = null;
971 try
972 { // send the Post
973 DeRezRequest.ContentLength = buffer.Length; //Count bytes to send
974 os = DeRezRequest.GetRequestStream();
975 os.Write(buffer, 0, buffer.Length); //Send it
976 os.Close();
977 m_log.InfoFormat("[OGP]: Derez Avatar Posted Rez Avatar request to remote sim {0}", CapAddress);
978 }
979 catch (WebException ex)
980 {
981 m_log.InfoFormat("[OGP] Bad send on de_rez_avatar {0}", ex.Message);
982 responseMap["connect"] = OSD.FromBoolean(false);
983
984 return responseMap;
985 }
986
987 m_log.Info("[OGP] waiting for a reply after rez avatar send");
988 string rez_avatar_reply = null;
989 { // get the response
990 try
991 {
992 WebResponse webResponse = DeRezRequest.GetResponse();
993 if (webResponse == null)
994 {
995 m_log.Info("[OGP:] Null reply on rez_avatar post");
996 }
997
998 StreamReader sr = new StreamReader(webResponse.GetResponseStream());
999 rez_avatar_reply = sr.ReadToEnd().Trim();
1000 m_log.InfoFormat("[OGP]: rez_avatar reply was {0} ", rez_avatar_reply);
1001
1002 }
1003 catch (WebException ex)
1004 {
1005 m_log.InfoFormat("[OGP]: exception on read after send of rez avatar {0}", ex.Message);
1006 responseMap["connect"] = OSD.FromBoolean(false);
1007
1008 return responseMap;
1009 }
1010 OSD rezResponse = null;
1011 try
1012 {
1013 rezResponse = OSDParser.DeserializeLLSDXml(rez_avatar_reply);
1014
1015 responseMap = (OSDMap)rezResponse;
1016 }
1017 catch (Exception ex)
1018 {
1019 m_log.InfoFormat("[OGP]: exception on parse of rez reply {0}", ex.Message);
1020 responseMap["connect"] = OSD.FromBoolean(false);
1021
1022 return responseMap;
1023 }
1024 }
1025 return responseMap;
1026 }
1027
1028 public OSD GenerateNoHandlerMessage()
1029 {
1030 OSDMap map = new OSDMap();
1031 map["reason"] = OSD.FromString("LLSDRequest");
1032 map["message"] = OSD.FromString("No handler registered for LLSD Requests");
1033 map["login"] = OSD.FromString("false");
1034 map["connect"] = OSD.FromString("false");
1035 return map;
1036 }
1037 public OSD GenerateNoStateMessage(UUID passedAvatar)
1038 {
1039 OSDMap map = new OSDMap();
1040 map["reason"] = OSD.FromString("derez failed");
1041 map["message"] = OSD.FromString("Unable to locate OGP state for avatar " + passedAvatar.ToString());
1042 map["login"] = OSD.FromString("false");
1043 map["connect"] = OSD.FromString("false");
1044 return map;
1045 }
1046 private bool TryGetAgentCircuitData(string path, out AgentCircuitData userdata)
1047 {
1048 userdata = null;
1049 lock (CapsLoginID)
1050 {
1051 if (CapsLoginID.ContainsKey(path))
1052 {
1053 userdata = CapsLoginID[path];
1054 DiscardUsedCap(path);
1055 return true;
1056 }
1057 }
1058 return false;
1059 }
1060
1061 private void DiscardUsedCap(string path)
1062 {
1063 CapsLoginID.Remove(path);
1064 }
1065
1066 private Scene GetRootScene()
1067 {
1068 Scene ReturnScene = null;
1069 lock (m_scene)
1070 {
1071 if (m_scene.Count > 0)
1072 {
1073 ReturnScene = m_scene[0];
1074 }
1075 }
1076
1077 return ReturnScene;
1078 }
1079
1080 private Scene GetScene(string scenename)
1081 {
1082 Scene ReturnScene = null;
1083 lock (m_scene)
1084 {
1085 foreach (Scene s in m_scene)
1086 {
1087 if (s.RegionInfo.RegionName.ToLower() == scenename)
1088 {
1089 ReturnScene = s;
1090 break;
1091 }
1092 }
1093 }
1094
1095 return ReturnScene;
1096 }
1097
1098 private ulong GetOSCompatibleRegionHandle(RegionInfo reg)
1099 {
1100 return Util.UIntsToLong(reg.RegionLocX, reg.RegionLocY);
1101 }
1102
1103 private OGPState InitializeNewState()
1104 {
1105 OGPState returnState = new OGPState();
1106 returnState.first_name = "";
1107 returnState.last_name = "";
1108 returnState.agent_id = UUID.Zero;
1109 returnState.local_agent_id = UUID.Zero;
1110 returnState.region_id = UUID.Zero;
1111 returnState.circuit_code = 0;
1112 returnState.secure_session_id = UUID.Zero;
1113 returnState.session_id = UUID.Zero;
1114 returnState.agent_access = true;
1115 returnState.god_level = 0;
1116 returnState.god_overide = false;
1117 returnState.identified = false;
1118 returnState.transacted = false;
1119 returnState.age_verified = false;
1120 returnState.limited_to_estate = 1;
1121 returnState.inventory_host = "http://inv4.mysql.aditi.lindenlab.com";
1122 returnState.allow_redirect = true;
1123 returnState.sim_access = "";
1124 returnState.src_can_see_mainland = true;
1125 returnState.src_estate_id = 1;
1126 returnState.src_version = 1;
1127 returnState.src_parent_estate_id = 1;
1128 returnState.visible_to_parent = true;
1129 returnState.teleported_into_region = "";
1130
1131 return returnState;
1132 }
1133
1134 private OGPState GetOGPState(UUID agentId)
1135 {
1136 lock (m_OGPState)
1137 {
1138 if (m_OGPState.ContainsKey(agentId))
1139 {
1140 return m_OGPState[agentId];
1141 }
1142 else
1143 {
1144 return InitializeNewState();
1145 }
1146 }
1147 }
1148
1149 public void DeleteOGPState(UUID agentId)
1150 {
1151 lock (m_OGPState)
1152 {
1153 if (m_OGPState.ContainsKey(agentId))
1154 m_OGPState.Remove(agentId);
1155 }
1156 }
1157
1158 private void UpdateOGPState(UUID agentId, OGPState state)
1159 {
1160 lock (m_OGPState)
1161 {
1162 if (m_OGPState.ContainsKey(agentId))
1163 {
1164 m_OGPState[agentId] = state;
1165 }
1166 else
1167 {
1168 m_OGPState.Add(agentId,state);
1169 }
1170 }
1171 }
1172 private bool SceneListDuplicateCheck(string str)
1173 {
1174 // no lock, called from locked space!
1175 bool found = false;
1176
1177 foreach (Scene s in m_scene)
1178 {
1179 if (s.RegionInfo.RegionName == str)
1180 {
1181 found = true;
1182 break;
1183 }
1184 }
1185
1186 return found;
1187 }
1188
1189 public void ShutdownConnection(UUID avatarId, OpenGridProtocolModule mod)
1190 {
1191 Scene homeScene = GetRootScene();
1192 ScenePresence avatar = null;
1193 if (homeScene.TryGetAvatar(avatarId,out avatar))
1194 {
1195 KillAUser ku = new KillAUser(avatar,mod);
1196 Thread ta = new Thread(ku.ShutdownNoLogout);
1197 ta.IsBackground = true;
1198 ta.Name = "ShutdownThread";
1199 ta.Start();
1200 }
1201 }
1202
1203 private string CreateRandomStr(int len)
1204 {
1205 Random rnd = new Random(System.Environment.TickCount);
1206 string returnstring = "";
1207 string chars = "abcdefghijklmnopqrstuvwxyz0123456789";
1208
1209 for (int i = 0; i < len; i++)
1210 {
1211 returnstring += chars.Substring(rnd.Next(chars.Length), 1);
1212 }
1213 return returnstring;
1214 }
1215 // Temporary hack to allow teleporting to and from Vaak
1216 private static bool customXertificateValidation(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
1217 {
1218 //if (cert.Subject == "E=root@lindenlab.com, CN=*.vaak.lindenlab.com, O=\"Linden Lab, Inc.\", L=San Francisco, S=California, C=US")
1219 //{
1220 return true;
1221 //}
1222
1223 //return false;
1224 }
1225 }
1226
1227 public class KillAUser
1228 {
1229 private ScenePresence avToBeKilled = null;
1230 private OpenGridProtocolModule m_mod = null;
1231
1232 public KillAUser(ScenePresence avatar, OpenGridProtocolModule mod)
1233 {
1234 avToBeKilled = avatar;
1235 m_mod = mod;
1236 }
1237
1238 public void ShutdownNoLogout()
1239 {
1240 UUID avUUID = UUID.Zero;
1241
1242 if (avToBeKilled != null)
1243 {
1244 avUUID = avToBeKilled.UUID;
1245 avToBeKilled.MakeChildAgent();
1246
1247 avToBeKilled.ControllingClient.SendLogoutPacketWhenClosing = false;
1248
1249 Thread.Sleep(30000);
1250
1251 // test for child agent because they might have come back
1252 if (avToBeKilled.IsChildAgent)
1253 {
1254 m_mod.DeleteOGPState(avUUID);
1255 avToBeKilled.ControllingClient.Close(true);
1256 }
1257 }
1258 }
1259
1260 }
1261
1262 public class MonoCert : ICertificatePolicy
1263 {
1264 #region ICertificatePolicy Members
1265
1266 public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem)
1267 {
1268 return true;
1269 }
1270
1271 #endregion
1272 }
1273}
diff --git a/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs
deleted file mode 100644
index f498f9a..0000000
--- a/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ /dev/null
@@ -1,332 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Drawing;
31using System.Drawing.Imaging;
32using OpenMetaverse;
33using OpenMetaverse.Imaging;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38
39namespace OpenSim.Region.Environment.Modules.Scripting.DynamicTexture
40{
41 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
42 {
43 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
44
45 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
46 new Dictionary<string, IDynamicTextureRender>();
47
48 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>();
49
50 #region IDynamicTextureManager Members
51
52 public void RegisterRender(string handleType, IDynamicTextureRender render)
53 {
54 if (!RenderPlugins.ContainsKey(handleType))
55 {
56 RenderPlugins.Add(handleType, render);
57 }
58 }
59
60 /// <summary>
61 /// Called by code which actually renders the dynamic texture to supply texture data.
62 /// </summary>
63 /// <param name="id"></param>
64 /// <param name="data"></param>
65 public void ReturnData(UUID id, byte[] data)
66 {
67 if (Updaters.ContainsKey(id))
68 {
69 DynamicTextureUpdater updater = Updaters[id];
70 if (RegisteredScenes.ContainsKey(updater.SimUUID))
71 {
72 Scene scene = RegisteredScenes[updater.SimUUID];
73 updater.DataReceived(data, scene);
74 }
75 }
76 }
77
78 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
79 string extraParams, int updateTimer)
80 {
81 return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255);
82 }
83
84 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
85 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
86 {
87 if (RenderPlugins.ContainsKey(contentType))
88 {
89 //Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType);
90
91 DynamicTextureUpdater updater = new DynamicTextureUpdater();
92 updater.SimUUID = simID;
93 updater.PrimID = primID;
94 updater.ContentType = contentType;
95 updater.Url = url;
96 updater.UpdateTimer = updateTimer;
97 updater.UpdaterID = UUID.Random();
98 updater.Params = extraParams;
99 updater.BlendWithOldTexture = SetBlending;
100 updater.FrontAlpha = AlphaValue;
101
102 if (!Updaters.ContainsKey(updater.UpdaterID))
103 {
104 Updaters.Add(updater.UpdaterID, updater);
105 }
106
107 RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams);
108 return updater.UpdaterID;
109 }
110 return UUID.Zero;
111 }
112
113 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
114 string extraParams, int updateTimer)
115 {
116 return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255);
117 }
118
119 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
120 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
121 {
122 if (RenderPlugins.ContainsKey(contentType))
123 {
124 DynamicTextureUpdater updater = new DynamicTextureUpdater();
125 updater.SimUUID = simID;
126 updater.PrimID = primID;
127 updater.ContentType = contentType;
128 updater.BodyData = data;
129 updater.UpdateTimer = updateTimer;
130 updater.UpdaterID = UUID.Random();
131 updater.Params = extraParams;
132 updater.BlendWithOldTexture = SetBlending;
133 updater.FrontAlpha = AlphaValue;
134
135 if (!Updaters.ContainsKey(updater.UpdaterID))
136 {
137 Updaters.Add(updater.UpdaterID, updater);
138 }
139
140 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
141 return updater.UpdaterID;
142 }
143 return UUID.Zero;
144 }
145
146 #endregion
147
148 #region IRegionModule Members
149
150 public void Initialise(Scene scene, IConfigSource config)
151 {
152 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
153 {
154 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
155 scene.RegisterModuleInterface<IDynamicTextureManager>(this);
156 }
157 }
158
159 public void PostInitialise()
160 {
161 }
162
163 public void Close()
164 {
165 }
166
167 public string Name
168 {
169 get { return "DynamicTextureModule"; }
170 }
171
172 public bool IsSharedModule
173 {
174 get { return true; }
175 }
176
177 #endregion
178
179 #region Nested type: DynamicTextureUpdater
180
181 public class DynamicTextureUpdater
182 {
183 public bool BlendWithOldTexture = false;
184 public string BodyData;
185 public string ContentType;
186 public byte FrontAlpha = 255;
187 public UUID LastAssetID;
188 public string Params;
189 public UUID PrimID;
190 public bool SetNewFrontAlpha = false;
191 public UUID SimUUID;
192 public UUID UpdaterID;
193 public int UpdateTimer;
194 public string Url;
195
196 public DynamicTextureUpdater()
197 {
198 LastAssetID = UUID.Zero;
199 UpdateTimer = 0;
200 BodyData = null;
201 }
202
203 /// <summary>
204 /// Called once new texture data has been received for this updater.
205 /// </summary>
206 public void DataReceived(byte[] data, Scene scene)
207 {
208 SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
209 byte[] assetData;
210 AssetBase oldAsset = null;
211
212 if (BlendWithOldTexture)
213 {
214 UUID lastTextureID = part.Shape.Textures.DefaultTexture.TextureID;
215 oldAsset = scene.AssetCache.GetAsset(lastTextureID, true);
216 if (oldAsset != null)
217 {
218 assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha);
219 }
220 else
221 {
222 assetData = new byte[data.Length];
223 Array.Copy(data, assetData, data.Length);
224 }
225 }
226 else
227 {
228 assetData = new byte[data.Length];
229 Array.Copy(data, assetData, data.Length);
230 }
231
232 // Create a new asset for user
233 AssetBase asset = new AssetBase();
234 asset.Metadata.FullID = UUID.Random();
235 asset.Data = assetData;
236 asset.Metadata.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000);
237 asset.Metadata.Type = 0;
238 asset.Metadata.Description = "dynamic image";
239 asset.Metadata.Local = false;
240 asset.Metadata.Temporary = true;
241 scene.AssetCache.AddAsset(asset);
242
243 LastAssetID = asset.Metadata.FullID;
244
245 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
246 if (cacheLayerDecode != null)
247 {
248 cacheLayerDecode.syncdecode(asset.Metadata.FullID, asset.Data);
249 }
250 cacheLayerDecode = null;
251
252 // mostly keep the values from before
253 Primitive.TextureEntry tmptex = part.Shape.Textures;
254
255 // remove the old asset from the cache
256 UUID oldID = tmptex.DefaultTexture.TextureID;
257 scene.AssetCache.ExpireAsset(oldID);
258
259 tmptex.DefaultTexture.TextureID = asset.Metadata.FullID;
260 // I'm pretty sure we always want to force this to true
261 tmptex.DefaultTexture.Fullbright = true;
262
263 part.Shape.Textures = tmptex;
264 part.ScheduleFullUpdate();
265 }
266
267 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
268 {
269 ManagedImage managedImage;
270 Image image;
271
272 if (OpenJPEG.DecodeToImage(frontImage, out managedImage, out image))
273 {
274 Bitmap image1 = new Bitmap(image);
275
276 if (OpenJPEG.DecodeToImage(backImage, out managedImage, out image))
277 {
278 Bitmap image2 = new Bitmap(image);
279
280 if (setNewAlpha)
281 SetAlpha(ref image1, newAlpha);
282
283 Bitmap joint = MergeBitMaps(image1, image2);
284
285 byte[] result = new byte[0];
286
287 try
288 {
289 result = OpenJPEG.EncodeFromImage(joint, true);
290 }
291 catch (Exception)
292 {
293 Console.WriteLine(
294 "[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Empty byte data returned!");
295 }
296
297 return result;
298 }
299 }
300
301 return null;
302 }
303
304 public Bitmap MergeBitMaps(Bitmap front, Bitmap back)
305 {
306 Bitmap joint;
307 Graphics jG;
308
309 joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb);
310 jG = Graphics.FromImage(joint);
311
312 jG.DrawImage(back, 0, 0, back.Width, back.Height);
313 jG.DrawImage(front, 0, 0, back.Width, back.Height);
314
315 return joint;
316 }
317
318 private void SetAlpha(ref Bitmap b, byte alpha)
319 {
320 for (int w = 0; w < b.Width; w++)
321 {
322 for (int h = 0; h < b.Height; h++)
323 {
324 b.SetPixel(w, h, Color.FromArgb(alpha, b.GetPixel(w, h)));
325 }
326 }
327 }
328 }
329
330 #endregion
331 }
332}
diff --git a/OpenSim/Region/Environment/Modules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/Environment/Modules/Scripting/EMailModules/EmailModule.cs
deleted file mode 100644
index 81ce761..0000000
--- a/OpenSim/Region/Environment/Modules/Scripting/EMailModules/EmailModule.cs
+++ /dev/null
@@ -1,288 +0,0 @@
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 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 */
27
28using System;
29using System.Reflection;
30using System.Collections.Generic;
31using System.Text.RegularExpressions;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36using log4net;
37using Nini.Config;
38using DotNetOpenMail;
39using DotNetOpenMail.SmtpAuth;
40
41namespace OpenSim.Region.Environment.Modules.Scripting.EmailModules
42{
43 public class EmailModule : IEmailModule
44 {
45 //
46 // Log
47 //
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 //
51 // Module vars
52 //
53 private IConfigSource m_Config;
54 private string m_HostName = string.Empty;
55 //private string m_RegionName = string.Empty;
56 private string SMTP_SERVER_HOSTNAME = string.Empty;
57 private int SMTP_SERVER_PORT = 25;
58 private string SMTP_SERVER_LOGIN = string.Empty;
59 private string SMTP_SERVER_PASSWORD = string.Empty;
60
61 // Scenes by Region Handle
62 private Dictionary<ulong, Scene> m_Scenes =
63 new Dictionary<ulong, Scene>();
64
65 private bool m_Enabled = false;
66
67 public void Initialise(Scene scene, IConfigSource config)
68 {
69 m_Config = config;
70 IConfig SMTPConfig;
71
72 //FIXME: RegionName is correct??
73 //m_RegionName = scene.RegionInfo.RegionName;
74
75 IConfig startupConfig = m_Config.Configs["Startup"];
76
77 m_Enabled = (startupConfig.GetString("emailmodule", "DefaultEmailModule") == "DefaultEmailModule");
78
79 //Load SMTP SERVER config
80 try
81 {
82 if ((SMTPConfig = m_Config.Configs["SMTP"]) == null)
83 {
84 m_log.InfoFormat("[SMTP] SMTP server not configured");
85 m_Enabled = false;
86 return;
87 }
88
89 if (!SMTPConfig.GetBoolean("enabled", false))
90 {
91 m_log.InfoFormat("[SMTP] module disabled in configuration");
92 m_Enabled = false;
93 return;
94 }
95
96 m_HostName = SMTPConfig.GetString("host_domain_header_from", m_HostName);
97 SMTP_SERVER_HOSTNAME = SMTPConfig.GetString("SMTP_SERVER_HOSTNAME",SMTP_SERVER_HOSTNAME);
98 SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT);
99 SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN);
100 SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD);
101 }
102 catch (Exception e)
103 {
104 m_log.Error("[EMAIL] DefaultEmailModule not configured: "+ e.Message);
105 m_Enabled = false;
106 return;
107 }
108
109 // It's a go!
110 if (m_Enabled)
111 {
112 lock (m_Scenes)
113 {
114 // Claim the interface slot
115 scene.RegisterModuleInterface<IEmailModule>(this);
116
117 // Add to scene list
118 if (m_Scenes.ContainsKey(scene.RegionInfo.RegionHandle))
119 {
120 m_Scenes[scene.RegionInfo.RegionHandle] = scene;
121 }
122 else
123 {
124 m_Scenes.Add(scene.RegionInfo.RegionHandle, scene);
125 }
126 }
127
128 m_log.Info("[EMAIL] Activated DefaultEmailModule");
129 }
130 }
131
132 public void PostInitialise()
133 {
134 }
135
136 public void Close()
137 {
138 }
139
140 public string Name
141 {
142 get { return "DefaultEmailModule"; }
143 }
144
145 public bool IsSharedModule
146 {
147 get { return true; }
148 }
149
150 /// <summary>
151 ///
152 /// </summary>
153 /// <param name="seconds"></param>
154 private void DelayInSeconds(int seconds)
155 {
156 TimeSpan DiffDelay = new TimeSpan(0, 0, seconds);
157 DateTime EndDelay = DateTime.Now.Add(DiffDelay);
158 while (DateTime.Now < EndDelay)
159 {
160 ;//Do nothing!!
161 }
162 }
163
164 private SceneObjectPart findPrim(UUID objectID, out string ObjectRegionName)
165 {
166 lock (m_Scenes)
167 {
168 foreach (Scene s in m_Scenes.Values)
169 {
170 SceneObjectPart part = s.GetSceneObjectPart(objectID);
171 if (part != null)
172 {
173 ObjectRegionName = s.RegionInfo.RegionName;
174 return part;
175 }
176 }
177 }
178 ObjectRegionName = string.Empty;
179 return null;
180 }
181
182 private void resolveNamePositionRegionName(UUID objectID, out string ObjectName, out string ObjectAbsolutePosition, out string ObjectRegionName)
183 {
184 string m_ObjectRegionName;
185 SceneObjectPart part = findPrim(objectID, out m_ObjectRegionName);
186 if (part != null)
187 {
188 ObjectAbsolutePosition = part.AbsolutePosition.ToString();
189 ObjectName = part.Name;
190 ObjectRegionName = m_ObjectRegionName;
191 return;
192 }
193 ObjectAbsolutePosition = part.AbsolutePosition.ToString();
194 ObjectName = part.Name;
195 ObjectRegionName = m_ObjectRegionName;
196 return;
197 }
198
199 /// <summary>
200 /// SendMail function utilized by llEMail
201 /// </summary>
202 /// <param name="objectID"></param>
203 /// <param name="address"></param>
204 /// <param name="subject"></param>
205 /// <param name="body"></param>
206 public void SendEmail(UUID objectID, string address, string subject, string body)
207 {
208 //Check if address is empty
209 if (address == string.Empty)
210 return;
211
212 //FIXED:Check the email is correct form in REGEX
213 string EMailpatternStrict = @"^(([^<>()[\]\\.,;:\s@\""]+"
214 + @"(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@"
215 + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
216 + @"\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+"
217 + @"[a-zA-Z]{2,}))$";
218 Regex EMailreStrict = new Regex(EMailpatternStrict);
219 bool isEMailStrictMatch = EMailreStrict.IsMatch(address);
220 if (!isEMailStrictMatch)
221 {
222 m_log.Error("[EMAIL] REGEX Problem in EMail Address: "+address);
223 return;
224 }
225 //FIXME:Check if subject + body = 4096 Byte
226 if ((subject.Length + body.Length) > 1024)
227 {
228 m_log.Error("[EMAIL] subject + body > 1024 Byte");
229 return;
230 }
231
232 try
233 {
234 string LastObjectName = string.Empty;
235 string LastObjectPosition = string.Empty;
236 string LastObjectRegionName = string.Empty;
237 //DONE: Message as Second Life style
238 //20 second delay - AntiSpam System - for now only 10 seconds
239 DelayInSeconds(10);
240 //Creation EmailMessage
241 EmailMessage emailMessage = new EmailMessage();
242 //From
243 emailMessage.FromAddress = new EmailAddress(objectID.ToString()+"@"+m_HostName);
244 //To - Only One
245 emailMessage.AddToAddress(new EmailAddress(address));
246 //Subject
247 emailMessage.Subject = subject;
248 //TEXT Body
249 resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName);
250 emailMessage.TextPart = new TextAttachment("Object-Name: " + LastObjectName +
251 "\r\nRegion: " + LastObjectRegionName + "\r\nLocal-Position: " +
252 LastObjectPosition+"\r\n\r\n\r\n" + body);
253 //HTML Body
254 emailMessage.HtmlPart = new HtmlAttachment("<html><body><p>" +
255 "<BR>Object-Name: " + LastObjectName +
256 "<BR>Region: " + LastObjectRegionName +
257 "<BR>Local-Position: " + LastObjectPosition + "<BR><BR><BR>"
258 +body+"\r\n</p></body><html>");
259
260 //Set SMTP SERVER config
261 SmtpServer smtpServer=new SmtpServer(SMTP_SERVER_HOSTNAME,SMTP_SERVER_PORT);
262 //Authentication
263 smtpServer.SmtpAuthToken=new SmtpAuthToken(SMTP_SERVER_LOGIN, SMTP_SERVER_PASSWORD);
264 //Send Email Message
265 emailMessage.Send(smtpServer);
266 //Log
267 m_log.Info("[EMAIL] EMail sent to: " + address + " from object: " + objectID.ToString());
268 }
269 catch (Exception e)
270 {
271 m_log.Error("[EMAIL] DefaultEmailModule Exception: "+e.Message);
272 return;
273 }
274 }
275
276 /// <summary>
277 ///
278 /// </summary>
279 /// <param name="objectID"></param>
280 /// <param name="sender"></param>
281 /// <param name="subject"></param>
282 /// <returns></returns>
283 public Email GetNextEmail(UUID objectID, string sender, string subject)
284 {
285 return null;
286 }
287 }
288}
diff --git a/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs
deleted file mode 100644
index faa6f3c..0000000
--- a/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ /dev/null
@@ -1,437 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Net;
32using System.Text;
33using System.Threading;
34using OpenMetaverse;
35using Nini.Config;
36using OpenSim.Framework;
37using OpenSim.Framework.Servers;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using System.Collections;
41
42/*****************************************************
43 *
44 * ScriptsHttpRequests
45 *
46 * Implements the llHttpRequest and http_response
47 * callback.
48 *
49 * Some stuff was already in LSLLongCmdHandler, and then
50 * there was this file with a stub class in it. So,
51 * I am moving some of the objects and functions out of
52 * LSLLongCmdHandler, such as the HttpRequestClass, the
53 * start and stop methods, and setting up pending and
54 * completed queues. These are processed in the
55 * LSLLongCmdHandler polling loop. Similiar to the
56 * XMLRPCModule, since that seems to work.
57 *
58 * //TODO
59 *
60 * This probably needs some throttling mechanism but
61 * it's wide open right now. This applies to both
62 * number of requests and data volume.
63 *
64 * Linden puts all kinds of header fields in the requests.
65 * Not doing any of that:
66 * User-Agent
67 * X-SecondLife-Shard
68 * X-SecondLife-Object-Name
69 * X-SecondLife-Object-Key
70 * X-SecondLife-Region
71 * X-SecondLife-Local-Position
72 * X-SecondLife-Local-Velocity
73 * X-SecondLife-Local-Rotation
74 * X-SecondLife-Owner-Name
75 * X-SecondLife-Owner-Key
76 *
77 * HTTPS support
78 *
79 * Configurable timeout?
80 * Configurable max response size?
81 * Configurable
82 *
83 * **************************************************/
84
85namespace OpenSim.Region.Environment.Modules.Scripting.HttpRequest
86{
87 public class HttpRequestModule : IRegionModule, IHttpRequestModule
88 {
89 private object HttpListLock = new object();
90 private int httpTimeout = 30000;
91 private string m_name = "HttpScriptRequests";
92
93 private string m_proxyurl = "";
94 private string m_proxyexcepts = "";
95
96 // <request id, HttpRequestClass>
97 private Dictionary<UUID, HttpRequestClass> m_pendingRequests;
98 private Scene m_scene;
99 // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
100
101 public HttpRequestModule()
102 {
103 }
104
105 #region IHttpRequestModule Members
106
107 public UUID MakeHttpRequest(string url, string parameters, string body)
108 {
109 return UUID.Zero;
110 }
111
112 public UUID StartHttpRequest(uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body)
113 {
114 UUID reqID = UUID.Random();
115 HttpRequestClass htc = new HttpRequestClass();
116
117 // Partial implementation: support for parameter flags needed
118 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
119 //
120 // Parameters are expected in {key, value, ... , key, value}
121 if (parameters != null)
122 {
123 string[] parms = parameters.ToArray();
124 for (int i = 0; i < parms.Length; i += 2)
125 {
126 switch (Int32.Parse(parms[i]))
127 {
128 case (int)HttpRequestConstants.HTTP_METHOD:
129
130 htc.HttpMethod = parms[i + 1];
131 break;
132
133 case (int)HttpRequestConstants.HTTP_MIMETYPE:
134
135 htc.HttpMIMEType = parms[i + 1];
136 break;
137
138 case (int)HttpRequestConstants.HTTP_BODY_MAXLENGTH:
139
140 // TODO implement me
141 break;
142
143 case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
144
145 // TODO implement me
146 break;
147 }
148 }
149 }
150
151 htc.LocalID = localID;
152 htc.ItemID = itemID;
153 htc.Url = url;
154 htc.ReqID = reqID;
155 htc.HttpTimeout = httpTimeout;
156 htc.OutboundBody = body;
157 htc.ResponseHeaders = headers;
158 htc.proxyurl = m_proxyurl;
159 htc.proxyexcepts = m_proxyexcepts;
160
161 lock (HttpListLock)
162 {
163 m_pendingRequests.Add(reqID, htc);
164 }
165
166 htc.Process();
167
168 return reqID;
169 }
170
171 public void StopHttpRequest(uint m_localID, UUID m_itemID)
172 {
173 if (m_pendingRequests != null)
174 {
175 lock (HttpListLock)
176 {
177 HttpRequestClass tmpReq;
178 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
179 {
180 tmpReq.Stop();
181 m_pendingRequests.Remove(m_itemID);
182 }
183 }
184 }
185 }
186
187 /*
188 * TODO
189 * Not sure how important ordering is is here - the next first
190 * one completed in the list is returned, based soley on its list
191 * position, not the order in which the request was started or
192 * finsihed. I thought about setting up a queue for this, but
193 * it will need some refactoring and this works 'enough' right now
194 */
195
196 public IServiceRequest GetNextCompletedRequest()
197 {
198 lock (HttpListLock)
199 {
200 foreach (UUID luid in m_pendingRequests.Keys)
201 {
202 HttpRequestClass tmpReq;
203
204 if (m_pendingRequests.TryGetValue(luid, out tmpReq))
205 {
206 if (tmpReq.Finished)
207 {
208 return tmpReq;
209 }
210 }
211 }
212 }
213 return null;
214 }
215
216 public void RemoveCompletedRequest(UUID id)
217 {
218 lock (HttpListLock)
219 {
220 HttpRequestClass tmpReq;
221 if (m_pendingRequests.TryGetValue(id, out tmpReq))
222 {
223 tmpReq.Stop();
224 tmpReq = null;
225 m_pendingRequests.Remove(id);
226 }
227 }
228 }
229
230 #endregion
231
232 #region IRegionModule Members
233
234 public void Initialise(Scene scene, IConfigSource config)
235 {
236 m_scene = scene;
237
238 m_scene.RegisterModuleInterface<IHttpRequestModule>(this);
239
240 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
241 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
242
243 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
244 }
245
246 public void PostInitialise()
247 {
248 }
249
250 public void Close()
251 {
252 }
253
254 public string Name
255 {
256 get { return m_name; }
257 }
258
259 public bool IsSharedModule
260 {
261 get { return true; }
262 }
263
264 #endregion
265 }
266
267 public class HttpRequestClass: IServiceRequest
268 {
269 // Constants for parameters
270 // public const int HTTP_BODY_MAXLENGTH = 2;
271 // public const int HTTP_METHOD = 0;
272 // public const int HTTP_MIMETYPE = 1;
273 // public const int HTTP_VERIFY_CERT = 3;
274 private bool _finished;
275 public bool Finished
276 {
277 get { return _finished; }
278 }
279 // public int HttpBodyMaxLen = 2048; // not implemented
280
281 // Parameter members and default values
282 public string HttpMethod = "GET";
283 public string HttpMIMEType = "text/plain;charset=utf-8";
284 public int HttpTimeout;
285 // public bool HttpVerifyCert = true; // not implemented
286 private Thread httpThread;
287
288 // Request info
289 private UUID _itemID;
290 public UUID ItemID
291 {
292 get { return _itemID; }
293 set { _itemID = value; }
294 }
295 private uint _localID;
296 public uint LocalID
297 {
298 get { return _localID; }
299 set { _localID = value; }
300 }
301 public DateTime Next;
302 public string proxyurl;
303 public string proxyexcepts;
304 public string OutboundBody;
305 private UUID _reqID;
306 public UUID ReqID
307 {
308 get { return _reqID; }
309 set { _reqID = value; }
310 }
311 public HttpWebRequest Request;
312 public string ResponseBody;
313 public List<string> ResponseMetadata;
314 public Dictionary<string, string> ResponseHeaders;
315 public int Status;
316 public string Url;
317
318 public void Process()
319 {
320 httpThread = new Thread(SendRequest);
321 httpThread.Name = "HttpRequestThread";
322 httpThread.Priority = ThreadPriority.BelowNormal;
323 httpThread.IsBackground = true;
324 _finished = false;
325 httpThread.Start();
326 ThreadTracker.Add(httpThread);
327 }
328
329 /*
330 * TODO: More work on the response codes. Right now
331 * returning 200 for success or 499 for exception
332 */
333
334 public void SendRequest()
335 {
336 HttpWebResponse response = null;
337 StringBuilder sb = new StringBuilder();
338 byte[] buf = new byte[8192];
339 string tempString = null;
340 int count = 0;
341
342 try
343 {
344 Request = (HttpWebRequest) WebRequest.Create(Url);
345 Request.Method = HttpMethod;
346 Request.ContentType = HttpMIMEType;
347
348 if (proxyurl != null && proxyurl.Length > 0)
349 {
350 if (proxyexcepts != null && proxyexcepts.Length > 0)
351 {
352 string[] elist = proxyexcepts.Split(';');
353 Request.Proxy = new WebProxy(proxyurl, true, elist);
354 }
355 else
356 {
357 Request.Proxy = new WebProxy(proxyurl, true);
358 }
359 }
360
361 foreach (KeyValuePair<string, string> entry in ResponseHeaders)
362 Request.Headers[entry.Key] = entry.Value;
363
364 // Encode outbound data
365 if (OutboundBody.Length > 0)
366 {
367 byte[] data = Encoding.UTF8.GetBytes(OutboundBody);
368
369 Request.ContentLength = data.Length;
370 Stream bstream = Request.GetRequestStream();
371 bstream.Write(data, 0, data.Length);
372 bstream.Close();
373 }
374
375 Request.Timeout = HttpTimeout;
376 // execute the request
377 response = (HttpWebResponse) Request.GetResponse();
378
379 Stream resStream = response.GetResponseStream();
380
381 do
382 {
383 // fill the buffer with data
384 count = resStream.Read(buf, 0, buf.Length);
385
386 // make sure we read some data
387 if (count != 0)
388 {
389 // translate from bytes to ASCII text
390 tempString = Encoding.UTF8.GetString(buf, 0, count);
391
392 // continue building the string
393 sb.Append(tempString);
394 }
395 } while (count > 0); // any more data to read?
396
397 ResponseBody = sb.ToString();
398 }
399 catch (Exception e)
400 {
401 if (e is WebException && ((WebException)e).Status == WebExceptionStatus.ProtocolError)
402 {
403 HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response;
404 Status = (int)webRsp.StatusCode;
405 ResponseBody = webRsp.StatusDescription;
406 }
407 else
408 {
409 Status = (int)OSHttpStatusCode.ClientErrorJoker;
410 ResponseBody = e.Message;
411 }
412
413 _finished = true;
414 return;
415 }
416 finally
417 {
418 if (response != null)
419 response.Close();
420 }
421
422 Status = (int)OSHttpStatusCode.SuccessOk;
423 _finished = true;
424 }
425
426 public void Stop()
427 {
428 try
429 {
430 httpThread.Abort();
431 }
432 catch (Exception)
433 {
434 }
435 }
436 }
437}
diff --git a/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs
deleted file mode 100644
index 0112ee6..0000000
--- a/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ /dev/null
@@ -1,229 +0,0 @@
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 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 */
27
28using System;
29using System.Drawing;
30using System.IO;
31using System.Net;
32using OpenMetaverse;
33using OpenMetaverse.Imaging;
34using Nini.Config;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38namespace OpenSim.Region.Environment.Modules.Scripting.LoadImageURL
39{
40 public class LoadImageURLModule : IRegionModule, IDynamicTextureRender
41 {
42 private string m_name = "LoadImageURL";
43 private Scene m_scene;
44 private IDynamicTextureManager m_textureManager;
45
46 private string m_proxyurl = "";
47 private string m_proxyexcepts = "";
48
49 #region IDynamicTextureRender Members
50
51 public string GetName()
52 {
53 return m_name;
54 }
55
56 public string GetContentType()
57 {
58 return ("image");
59 }
60
61 public bool SupportsAsynchronous()
62 {
63 return true;
64 }
65
66 public byte[] ConvertUrl(string url, string extraParams)
67 {
68 return null;
69 }
70
71 public byte[] ConvertStream(Stream data, string extraParams)
72 {
73 return null;
74 }
75
76 public bool AsyncConvertUrl(UUID id, string url, string extraParams)
77 {
78 MakeHttpRequest(url, id);
79 return true;
80 }
81
82 public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
83 {
84 return false;
85 }
86
87 #endregion
88
89 #region IRegionModule Members
90
91 public void Initialise(Scene scene, IConfigSource config)
92 {
93 if (m_scene == null)
94 {
95 m_scene = scene;
96 }
97
98 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
99 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
100 }
101
102 public void PostInitialise()
103 {
104 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
105 if (m_textureManager != null)
106 {
107 m_textureManager.RegisterRender(GetContentType(), this);
108 }
109 }
110
111 public void Close()
112 {
113 }
114
115 public string Name
116 {
117 get { return m_name; }
118 }
119
120 public bool IsSharedModule
121 {
122 get { return true; }
123 }
124
125 #endregion
126
127 private void MakeHttpRequest(string url, UUID requestID)
128 {
129 WebRequest request = HttpWebRequest.Create(url);
130
131 if (m_proxyurl != null && m_proxyurl.Length > 0)
132 {
133 if (m_proxyexcepts != null && m_proxyexcepts.Length > 0)
134 {
135 string[] elist = m_proxyexcepts.Split(';');
136 request.Proxy = new WebProxy(m_proxyurl, true, elist);
137 }
138 else
139 {
140 request.Proxy = new WebProxy(m_proxyurl, true);
141 }
142 }
143
144 RequestState state = new RequestState((HttpWebRequest) request, requestID);
145 // IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
146 request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
147
148 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
149 state.TimeOfRequest = (int) t.TotalSeconds;
150 }
151
152 private void HttpRequestReturn(IAsyncResult result)
153 {
154 RequestState state = (RequestState) result.AsyncState;
155 WebRequest request = (WebRequest) state.Request;
156 try
157 {
158 HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
159 if (response.StatusCode == HttpStatusCode.OK)
160 {
161 Bitmap image = new Bitmap(response.GetResponseStream());
162 Size newsize;
163
164 // TODO: make this a bit less hard coded
165 if ((image.Height < 64) && (image.Width < 64))
166 {
167 newsize = new Size(32, 32);
168 }
169 else if ((image.Height < 128) && (image.Width < 128))
170 {
171 newsize = new Size(64, 64);
172 }
173 else if ((image.Height < 256) && (image.Width < 256))
174 {
175 newsize = new Size(128, 128);
176 }
177 else if ((image.Height < 512 && image.Width < 512))
178 {
179 newsize = new Size(256, 256);
180 }
181 else if ((image.Height < 1024 && image.Width < 1024))
182 {
183 newsize = new Size(512, 512);
184 }
185 else
186 {
187 newsize = new Size(1024, 1024);
188 }
189
190 Bitmap resize = new Bitmap(image, newsize);
191 byte[] imageJ2000 = new byte[0];
192
193 try
194 {
195 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
196 }
197 catch (Exception)
198 {
199 Console.WriteLine(
200 "[LOADIMAGEURLMODULE]: OpenJpeg Encode Failed. Empty byte data returned!");
201 }
202
203 m_textureManager.ReturnData(state.RequestID, imageJ2000);
204 }
205 }
206 catch (WebException)
207 {
208
209 }
210 }
211
212 #region Nested type: RequestState
213
214 public class RequestState
215 {
216 public HttpWebRequest Request = null;
217 public UUID RequestID = UUID.Zero;
218 public int TimeOfRequest = 0;
219
220 public RequestState(HttpWebRequest request, UUID requestID)
221 {
222 Request = request;
223 RequestID = requestID;
224 }
225 }
226
227 #endregion
228 }
229}
diff --git a/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs
deleted file mode 100644
index 60806a7..0000000
--- a/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs
+++ /dev/null
@@ -1,515 +0,0 @@
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 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 */
27
28using System;
29using System.Drawing;
30using System.Drawing.Imaging;
31using System.Globalization;
32using System.IO;
33using System.Net;
34using OpenMetaverse;
35using OpenMetaverse.Imaging;
36using Nini.Config;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39
40//using Cairo;
41
42namespace OpenSim.Region.Environment.Modules.Scripting.VectorRender
43{
44 public class VectorRenderModule : IRegionModule, IDynamicTextureRender
45 {
46 private string m_name = "VectorRenderModule";
47 private Scene m_scene;
48 private IDynamicTextureManager m_textureManager;
49
50 public VectorRenderModule()
51 {
52 }
53
54 #region IDynamicTextureRender Members
55
56 public string GetContentType()
57 {
58 return ("vector");
59 }
60
61 public string GetName()
62 {
63 return m_name;
64 }
65
66 public bool SupportsAsynchronous()
67 {
68 return true;
69 }
70
71 public byte[] ConvertUrl(string url, string extraParams)
72 {
73 return null;
74 }
75
76 public byte[] ConvertStream(Stream data, string extraParams)
77 {
78 return null;
79 }
80
81 public bool AsyncConvertUrl(UUID id, string url, string extraParams)
82 {
83 return false;
84 }
85
86 public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
87 {
88 Draw(bodyData, id, extraParams);
89 return true;
90 }
91
92 #endregion
93
94 #region IRegionModule Members
95
96 public void Initialise(Scene scene, IConfigSource config)
97 {
98 if (m_scene == null)
99 {
100 m_scene = scene;
101 }
102 }
103
104 public void PostInitialise()
105 {
106 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
107 if (m_textureManager != null)
108 {
109 m_textureManager.RegisterRender(GetContentType(), this);
110 }
111 }
112
113 public void Close()
114 {
115 }
116
117 public string Name
118 {
119 get { return m_name; }
120 }
121
122 public bool IsSharedModule
123 {
124 get { return true; }
125 }
126
127 #endregion
128
129 private void Draw(string data, UUID id, string extraParams)
130 {
131 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
132 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
133 int width = 256;
134 int height = 256;
135 int alpha = 255; // 0 is transparent
136
137 char[] paramDelimiter = { ',' };
138 char[] nvpDelimiter = { ':' };
139
140 extraParams = extraParams.Trim();
141 extraParams = extraParams.ToLower();
142
143 string[] nvps = extraParams.Split(paramDelimiter);
144
145 int temp = -1;
146 foreach (string pair in nvps)
147 {
148 string[] nvp = pair.Split(nvpDelimiter);
149 string name = "";
150 string value = "";
151
152 if (nvp[0] != null)
153 {
154 name = nvp[0].Trim();
155 }
156
157 if (nvp.Length == 2)
158 {
159 value = nvp[1].Trim();
160 }
161
162 switch (name)
163 {
164 case "width":
165 temp = parseIntParam(value);
166 if (temp != -1)
167 {
168 if (temp < 1)
169 {
170 width = 1;
171 }
172 else if (temp > 2048)
173 {
174 width = 2048;
175 }
176 else
177 {
178 width = temp;
179 }
180 }
181 break;
182 case "height":
183 temp = parseIntParam(value);
184 if (temp != -1)
185 {
186 if (temp < 1)
187 {
188 height = 1;
189 }
190 else if (temp > 2048)
191 {
192 height = 2048;
193 }
194 else
195 {
196 height = temp;
197 }
198 }
199 break;
200 case "alpha":
201 temp = parseIntParam(value);
202 if (temp != -1)
203 {
204 if (temp < 0)
205 {
206 alpha = 0;
207 }
208 else if (temp > 255)
209 {
210 alpha = 255;
211 }
212 else
213 {
214 alpha = temp;
215 }
216 }
217 break;
218 case "":
219 // blank string has been passed do nothing just use defaults
220 break;
221 default: // this is all for backwards compat, all a bit ugly hopfully can be removed in future
222 // could be either set alpha or just an int
223 if (name == "setalpha")
224 {
225 alpha = 0; // set the texture to have transparent background (maintains backwards compat)
226 }
227 else
228 {
229 // this function used to accept an int on its own that represented both
230 // width and height, this is to maintain backwards compat, could be removed
231 // but would break existing scripts
232 temp = parseIntParam(name);
233 if (temp != -1)
234 {
235 if (temp > 1024)
236 temp = 1024;
237
238 if (temp < 128)
239 temp = 128;
240
241 width = temp;
242 height = temp;
243 }
244 }
245 break;
246 }
247
248 }
249
250 Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
251
252 Graphics graph = Graphics.FromImage(bitmap);
253
254 // this is really just to save people filling the
255 // background white in their scripts, only do when fully opaque
256 if (alpha == 255)
257 {
258 graph.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height);
259 }
260
261 for (int w = 0; w < bitmap.Width; w++)
262 {
263 for (int h = 0; h < bitmap.Height; h++)
264 {
265 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
266 }
267 }
268
269
270 GDIDraw(data, graph);
271
272 byte[] imageJ2000 = new byte[0];
273
274 try
275 {
276 imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true);
277 }
278 catch (Exception)
279 {
280 Console.WriteLine(
281 "[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Empty byte data returned!");
282 }
283 m_textureManager.ReturnData(id, imageJ2000);
284 }
285
286 private int parseIntParam(string strInt)
287 {
288 int parsed;
289 try
290 {
291 parsed = Convert.ToInt32(strInt);
292 }
293 catch (Exception)
294 {
295 //Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used
296 // Console.WriteLine("Problem with Draw. Please verify parameters." + e.ToString());
297 parsed = -1;
298 }
299
300 return parsed;
301
302 }
303
304
305/*
306 private void CairoDraw(string data, System.Drawing.Graphics graph)
307 {
308 using (Win32Surface draw = new Win32Surface(graph.GetHdc()))
309 {
310 Context contex = new Context(draw);
311
312 contex.Antialias = Antialias.None; //fastest method but low quality
313 contex.LineWidth = 7;
314 char[] lineDelimiter = { ';' };
315 char[] partsDelimiter = { ',' };
316 string[] lines = data.Split(lineDelimiter);
317
318 foreach (string line in lines)
319 {
320 string nextLine = line.Trim();
321
322 if (nextLine.StartsWith("MoveTO"))
323 {
324 float x = 0;
325 float y = 0;
326 GetParams(partsDelimiter, ref nextLine, ref x, ref y);
327 contex.MoveTo(x, y);
328 }
329 else if (nextLine.StartsWith("LineTo"))
330 {
331 float x = 0;
332 float y = 0;
333 GetParams(partsDelimiter, ref nextLine, ref x, ref y);
334 contex.LineTo(x, y);
335 contex.Stroke();
336 }
337 }
338 }
339 graph.ReleaseHdc();
340 }
341*/
342
343 private void GDIDraw(string data, Graphics graph)
344 {
345 Point startPoint = new Point(0, 0);
346 Point endPoint = new Point(0, 0);
347 Pen drawPen = new Pen(Color.Black, 7);
348 string fontName = "Arial";
349 float fontSize = 14;
350 Font myFont = new Font(fontName, fontSize);
351 SolidBrush myBrush = new SolidBrush(Color.Black);
352 char[] lineDelimiter = {';'};
353 char[] partsDelimiter = {','};
354 string[] lines = data.Split(lineDelimiter);
355
356 foreach (string line in lines)
357 {
358 string nextLine = line.Trim();
359 //replace with switch, or even better, do some proper parsing
360 if (nextLine.StartsWith("MoveTo"))
361 {
362 float x = 0;
363 float y = 0;
364 GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y);
365 startPoint.X = (int) x;
366 startPoint.Y = (int) y;
367 }
368 else if (nextLine.StartsWith("LineTo"))
369 {
370 float x = 0;
371 float y = 0;
372 GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y);
373 endPoint.X = (int) x;
374 endPoint.Y = (int) y;
375 graph.DrawLine(drawPen, startPoint, endPoint);
376 startPoint.X = endPoint.X;
377 startPoint.Y = endPoint.Y;
378 }
379 else if (nextLine.StartsWith("Text"))
380 {
381 nextLine = nextLine.Remove(0, 4);
382 nextLine = nextLine.Trim();
383 graph.DrawString(nextLine, myFont, myBrush, startPoint);
384 }
385 else if (nextLine.StartsWith("Image"))
386 {
387 float x = 0;
388 float y = 0;
389 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
390 endPoint.X = (int) x;
391 endPoint.Y = (int) y;
392 Image image = ImageHttpRequest(nextLine);
393 graph.DrawImage(image, (float) startPoint.X, (float) startPoint.Y, x, y);
394 startPoint.X += endPoint.X;
395 startPoint.Y += endPoint.Y;
396 }
397 else if (nextLine.StartsWith("Rectangle"))
398 {
399 float x = 0;
400 float y = 0;
401 GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y);
402 endPoint.X = (int) x;
403 endPoint.Y = (int) y;
404 graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
405 startPoint.X += endPoint.X;
406 startPoint.Y += endPoint.Y;
407 }
408 else if (nextLine.StartsWith("FillRectangle"))
409 {
410 float x = 0;
411 float y = 0;
412 GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y);
413 endPoint.X = (int) x;
414 endPoint.Y = (int) y;
415 graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
416 startPoint.X += endPoint.X;
417 startPoint.Y += endPoint.Y;
418 }
419 else if (nextLine.StartsWith("Ellipse"))
420 {
421 float x = 0;
422 float y = 0;
423 GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y);
424 endPoint.X = (int) x;
425 endPoint.Y = (int) y;
426 graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
427 startPoint.X += endPoint.X;
428 startPoint.Y += endPoint.Y;
429 }
430 else if (nextLine.StartsWith("FontSize"))
431 {
432 nextLine = nextLine.Remove(0, 8);
433 nextLine = nextLine.Trim();
434 fontSize = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture);
435 myFont = new Font(fontName, fontSize);
436 }
437 else if (nextLine.StartsWith("FontName"))
438 {
439 nextLine = nextLine.Remove(0, 8);
440 fontName = nextLine.Trim();
441 myFont = new Font(fontName, fontSize);
442 }
443 else if (nextLine.StartsWith("PenSize"))
444 {
445 nextLine = nextLine.Remove(0, 7);
446 nextLine = nextLine.Trim();
447 float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture);
448 drawPen.Width = size;
449 }
450 else if (nextLine.StartsWith("PenColour"))
451 {
452 nextLine = nextLine.Remove(0, 9);
453 nextLine = nextLine.Trim();
454 int hex = 0;
455
456 Color newColour;
457 if (Int32.TryParse(nextLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex))
458 {
459 newColour = Color.FromArgb(hex);
460 }
461 else
462 {
463 // this doesn't fail, it just returns black if nothing is found
464 newColour = Color.FromName(nextLine);
465 }
466
467 myBrush.Color = newColour;
468 drawPen.Color = newColour;
469 }
470 }
471 }
472
473 private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y)
474 {
475 line = line.Remove(0, startLength);
476 string[] parts = line.Split(partsDelimiter);
477 if (parts.Length == 2)
478 {
479 string xVal = parts[0].Trim();
480 string yVal = parts[1].Trim();
481 x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
482 y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture);
483 }
484 else if (parts.Length > 2)
485 {
486 string xVal = parts[0].Trim();
487 string yVal = parts[1].Trim();
488 x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
489 y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture);
490
491 line = "";
492 for (int i = 2; i < parts.Length; i++)
493 {
494 line = line + parts[i].Trim();
495 line = line + " ";
496 }
497 }
498 }
499
500 private Bitmap ImageHttpRequest(string url)
501 {
502 WebRequest request = HttpWebRequest.Create(url);
503//Ckrinke: Comment out for now as 'str' is unused. Bring it back into play later when it is used.
504//Ckrinke Stream str = null;
505 HttpWebResponse response = (HttpWebResponse) (request).GetResponse();
506 if (response.StatusCode == HttpStatusCode.OK)
507 {
508 Bitmap image = new Bitmap(response.GetResponseStream());
509 return image;
510 }
511
512 return null;
513 }
514 }
515}
diff --git a/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs
deleted file mode 100644
index 258734d..0000000
--- a/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs
+++ /dev/null
@@ -1,726 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using OpenMetaverse;
32using Nini.Config;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36
37// using log4net;
38// using System.Reflection;
39
40
41/*****************************************************
42 *
43 * WorldCommModule
44 *
45 *
46 * Holding place for world comms - basically llListen
47 * function implementation.
48 *
49 * lLListen(integer channel, string name, key id, string msg)
50 * The name, id, and msg arguments specify the filtering
51 * criteria. You can pass the empty string
52 * (or NULL_KEY for id) for these to set a completely
53 * open filter; this causes the listen() event handler to be
54 * invoked for all chat on the channel. To listen only
55 * for chat spoken by a specific object or avatar,
56 * specify the name and/or id arguments. To listen
57 * only for a specific command, specify the
58 * (case-sensitive) msg argument. If msg is not empty,
59 * listener will only hear strings which are exactly equal
60 * to msg. You can also use all the arguments to establish
61 * the most restrictive filtering criteria.
62 *
63 * It might be useful for each listener to maintain a message
64 * digest, with a list of recent messages by UUID. This can
65 * be used to prevent in-world repeater loops. However, the
66 * linden functions do not have this capability, so for now
67 * thats the way it works.
68 * Instead it blocks messages originating from the same prim.
69 * (not Object!)
70 *
71 * For LSL compliance, note the following:
72 * (Tested again 1.21.1 on May 2, 2008)
73 * 1. 'id' has to be parsed into a UUID. None-UUID keys are
74 * to be replaced by the ZeroID key. (Well, TryParse does
75 * that for us.
76 * 2. Setting up an listen event from the same script, with the
77 * same filter settings (including step 1), returns the same
78 * handle as the original filter.
79 * 3. (TODO) handles should be script-local. Starting from 1.
80 * Might be actually easier to map the global handle into
81 * script-local handle in the ScriptEngine. Not sure if its
82 * worth the effort tho.
83 *
84 * **************************************************/
85
86namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm
87{
88 public class WorldCommModule : IRegionModule, IWorldComm
89 {
90 // private static readonly ILog m_log =
91 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
92
93 private ListenerManager m_listenerManager;
94 private Queue m_pending;
95 private Queue m_pendingQ;
96 private Scene m_scene;
97 private int m_whisperdistance = 10;
98 private int m_saydistance = 30;
99 private int m_shoutdistance = 100;
100
101 #region IRegionModule Members
102
103 public void Initialise(Scene scene, IConfigSource config)
104 {
105 // wrap this in a try block so that defaults will work if
106 // the config file doesn't specify otherwise.
107 int maxlisteners = 1000;
108 int maxhandles = 64;
109 try
110 {
111 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
112 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
113 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
114 maxlisteners = config.Configs["Chat"].GetInt("max_listens_per_region", maxlisteners);
115 maxhandles = config.Configs["Chat"].GetInt("max_listens_per_script", maxhandles);
116 }
117 catch (Exception)
118 {
119 }
120 if (maxlisteners < 1) maxlisteners = int.MaxValue;
121 if (maxhandles < 1) maxhandles = int.MaxValue;
122
123 m_scene = scene;
124 m_scene.RegisterModuleInterface<IWorldComm>(this);
125 m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
126 m_scene.EventManager.OnChatFromClient += DeliverClientMessage;
127 m_scene.EventManager.OnChatBroadcast += DeliverClientMessage;
128 m_pendingQ = new Queue();
129 m_pending = Queue.Synchronized(m_pendingQ);
130 }
131
132 public void PostInitialise()
133 {
134 }
135
136 public void Close()
137 {
138 }
139
140 public string Name
141 {
142 get { return "WorldCommModule"; }
143 }
144
145 public bool IsSharedModule
146 {
147 get { return false; }
148 }
149
150 #endregion
151
152 #region IWorldComm Members
153
154 /// <summary>
155 /// Create a listen event callback with the specified filters.
156 /// The parameters localID,itemID are needed to uniquely identify
157 /// the script during 'peek' time. Parameter hostID is needed to
158 /// determine the position of the script.
159 /// </summary>
160 /// <param name="localID">localID of the script engine</param>
161 /// <param name="itemID">UUID of the script engine</param>
162 /// <param name="hostID">UUID of the SceneObjectPart</param>
163 /// <param name="channel">channel to listen on</param>
164 /// <param name="name">name to filter on</param>
165 /// <param name="id">key to filter on (user given, could be totally faked)</param>
166 /// <param name="msg">msg to filter on</param>
167 /// <returns>number of the scripts handle</returns>
168 public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
169 {
170 return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg);
171 }
172
173 /// <summary>
174 /// Sets the listen event with handle as active (active = TRUE) or inactive (active = FALSE).
175 /// The handle used is returned from Listen()
176 /// </summary>
177 /// <param name="itemID">UUID of the script engine</param>
178 /// <param name="handle">handle returned by Listen()</param>
179 /// <param name="active">temp. activate or deactivate the Listen()</param>
180 public void ListenControl(UUID itemID, int handle, int active)
181 {
182 if (active == 1)
183 m_listenerManager.Activate(itemID, handle);
184 else if (active == 0)
185 m_listenerManager.Dectivate(itemID, handle);
186 }
187
188 /// <summary>
189 /// Removes the listen event callback with handle
190 /// </summary>
191 /// <param name="itemID">UUID of the script engine</param>
192 /// <param name="handle">handle returned by Listen()</param>
193 public void ListenRemove(UUID itemID, int handle)
194 {
195 m_listenerManager.Remove(itemID, handle);
196 }
197
198 /// <summary>
199 /// Removes all listen event callbacks for the given itemID
200 /// (script engine)
201 /// </summary>
202 /// <param name="itemID">UUID of the script engine</param>
203 public void DeleteListener(UUID itemID)
204 {
205 m_listenerManager.DeleteListener(itemID);
206 }
207
208
209 protected static Vector3 CenterOfRegion = new Vector3(128, 128, 20);
210
211 public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg)
212 {
213 Vector3 position;
214 SceneObjectPart source;
215 ScenePresence avatar;
216
217 if ((source = m_scene.GetSceneObjectPart(id)) != null)
218 position = source.AbsolutePosition;
219 else if ((avatar = m_scene.GetScenePresence(id)) != null)
220 position = avatar.AbsolutePosition;
221 else if (ChatTypeEnum.Region == type)
222 position = CenterOfRegion;
223 else
224 return;
225
226 DeliverMessage(type, channel, name, id, msg, position);
227 }
228
229 /// <summary>
230 /// This method scans over the objects which registered an interest in listen callbacks.
231 /// For everyone it finds, it checks if it fits the given filter. If it does, then
232 /// enqueue the message for delivery to the objects listen event handler.
233 /// The enqueued ListenerInfo no longer has filter values, but the actually trigged values.
234 /// Objects that do an llSay have their messages delivered here and for nearby avatars,
235 /// the OnChatFromClient event is used.
236 /// </summary>
237 /// <param name="type">type of delvery (whisper,say,shout or regionwide)</param>
238 /// <param name="channel">channel to sent on</param>
239 /// <param name="name">name of sender (object or avatar)</param>
240 /// <param name="id">key of sender (object or avatar)</param>
241 /// <param name="msg">msg to sent</param>
242 public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg, Vector3 position)
243 {
244 // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}",
245 // type, channel, name, id, msg);
246
247 // Determine which listen event filters match the given set of arguments, this results
248 // in a limited set of listeners, each belonging a host. If the host is in range, add them
249 // to the pending queue.
250 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
251 {
252 // Dont process if this message is from yourself!
253 if (li.GetHostID().Equals(id))
254 continue;
255
256 SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID());
257 if (sPart == null)
258 continue;
259
260 double dis = Util.GetDistanceTo(sPart.AbsolutePosition, position);
261 switch (type)
262 {
263 case ChatTypeEnum.Whisper:
264 if (dis < m_whisperdistance)
265 {
266 lock (m_pending.SyncRoot)
267 {
268 m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
269 }
270 }
271 break;
272
273 case ChatTypeEnum.Say:
274 if (dis < m_saydistance)
275 {
276 lock (m_pending.SyncRoot)
277 {
278 m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
279 }
280 }
281 break;
282
283 case ChatTypeEnum.Shout:
284 if (dis < m_shoutdistance)
285 {
286 lock (m_pending.SyncRoot)
287 {
288 m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
289 }
290 }
291 break;
292
293 case ChatTypeEnum.Region:
294 lock (m_pending.SyncRoot)
295 {
296 m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
297 }
298 break;
299 }
300 }
301 }
302
303 /// <summary>
304 /// Are there any listen events ready to be dispatched?
305 /// </summary>
306 /// <returns>boolean indication</returns>
307 public bool HasMessages()
308 {
309 return (m_pending.Count > 0);
310 }
311
312 /// <summary>
313 /// Pop the first availlable listen event from the queue
314 /// </summary>
315 /// <returns>ListenerInfo with filter filled in</returns>
316 public IWorldCommListenerInfo GetNextMessage()
317 {
318 ListenerInfo li = null;
319
320 lock (m_pending.SyncRoot)
321 {
322 li = (ListenerInfo) m_pending.Dequeue();
323 }
324
325 return li;
326 }
327
328 #endregion
329
330 /********************************************************************
331 *
332 * Listener Stuff
333 *
334 * *****************************************************************/
335
336 private void DeliverClientMessage(Object sender, OSChatMessage e)
337 {
338 if (null != e.Sender)
339 DeliverMessage(e.Type, e.Channel, e.Sender.Name, e.Sender.AgentId, e.Message, e.Position);
340 else
341 DeliverMessage(e.Type, e.Channel, e.From, UUID.Zero, e.Message, e.Position);
342 }
343
344 public Object[] GetSerializationData(UUID itemID)
345 {
346 return m_listenerManager.GetSerializationData(itemID);
347 }
348
349 public void CreateFromData(uint localID, UUID itemID, UUID hostID,
350 Object[] data)
351 {
352 m_listenerManager.AddFromData(localID, itemID, hostID, data);
353 }
354 }
355
356 public class ListenerManager
357 {
358 private Dictionary<int, List<ListenerInfo>> m_listeners = new Dictionary<int, List<ListenerInfo>>();
359 private int m_maxlisteners;
360 private int m_maxhandles;
361 private int m_curlisteners;
362
363 public ListenerManager(int maxlisteners, int maxhandles)
364 {
365 m_maxlisteners = maxlisteners;
366 m_maxhandles = maxhandles;
367 m_curlisteners = 0;
368 }
369
370 public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
371 {
372 // do we already have a match on this particular filter event?
373 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg);
374
375 if (coll.Count > 0)
376 {
377 // special case, called with same filter settings, return same handle
378 // (2008-05-02, tested on 1.21.1 server, still holds)
379 return coll[0].GetHandle();
380 }
381
382 if (m_curlisteners < m_maxlisteners)
383 {
384 int newHandle = GetNewHandle(itemID);
385
386 if (newHandle > 0)
387 {
388 ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg);
389
390 lock (m_listeners)
391 {
392 List<ListenerInfo> listeners;
393 if (!m_listeners.TryGetValue(channel,out listeners))
394 {
395 listeners = new List<ListenerInfo>();
396 m_listeners.Add(channel, listeners);
397 }
398 listeners.Add(li);
399 m_curlisteners++;
400 }
401
402 return newHandle;
403 }
404 }
405 return -1;
406 }
407
408 public void Remove(UUID itemID, int handle)
409 {
410 lock (m_listeners)
411 {
412 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners)
413 {
414 foreach (ListenerInfo li in lis.Value)
415 {
416 if (li.GetItemID().Equals(itemID) && li.GetHandle().Equals(handle))
417 {
418 lis.Value.Remove(li);
419 if (lis.Value.Count == 0)
420 {
421 m_listeners.Remove(lis.Key);
422 m_curlisteners--;
423 }
424 // there should be only one, so we bail out early
425 return;
426 }
427 }
428 }
429 }
430 }
431
432 public void DeleteListener(UUID itemID)
433 {
434 List<int> emptyChannels = new List<int>();
435 List<ListenerInfo> removedListeners = new List<ListenerInfo>();
436
437 lock (m_listeners)
438 {
439 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners)
440 {
441 foreach (ListenerInfo li in lis.Value)
442 {
443 if (li.GetItemID().Equals(itemID))
444 {
445 // store them first, else the enumerated bails on us
446 removedListeners.Add(li);
447 }
448 }
449 foreach (ListenerInfo li in removedListeners)
450 {
451 lis.Value.Remove(li);
452 m_curlisteners--;
453 }
454 removedListeners.Clear();
455 if (lis.Value.Count == 0)
456 {
457 // again, store first, remove later
458 emptyChannels.Add(lis.Key);
459 }
460 }
461 foreach (int channel in emptyChannels)
462 {
463 m_listeners.Remove(channel);
464 }
465 }
466 }
467
468 public void Activate(UUID itemID, int handle)
469 {
470 lock (m_listeners)
471 {
472 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners)
473 {
474 foreach (ListenerInfo li in lis.Value)
475 {
476 if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle)
477 {
478 li.Activate();
479 // only one, bail out
480 return;
481 }
482 }
483 }
484 }
485 }
486
487 public void Dectivate(UUID itemID, int handle)
488 {
489 lock (m_listeners)
490 {
491 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners)
492 {
493 foreach (ListenerInfo li in lis.Value)
494 {
495 if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle)
496 {
497 li.Deactivate();
498 // only one, bail out
499 return;
500 }
501 }
502 }
503 }
504 }
505
506 // non-locked access, since its always called in the context of the lock
507 private int GetNewHandle(UUID itemID)
508 {
509 List<int> handles = new List<int>();
510
511 // build a list of used keys for this specific itemID...
512 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners)
513 {
514 foreach (ListenerInfo li in lis.Value)
515 {
516 if (li.GetItemID().Equals(itemID))
517 handles.Add(li.GetHandle());
518 }
519 }
520
521 // Note: 0 is NOT a valid handle for llListen() to return
522 for (int i = 1; i <= m_maxhandles; i++)
523 {
524 if (!handles.Contains(i))
525 return i;
526 }
527
528 return -1;
529 }
530
531 // Theres probably a more clever and efficient way to
532 // do this, maybe with regex.
533 // PM2008: Ha, one could even be smart and define a specialized Enumerator.
534 public List<ListenerInfo> GetListeners(UUID itemID, int channel, string name, UUID id, string msg)
535 {
536 List<ListenerInfo> collection = new List<ListenerInfo>();
537
538 lock (m_listeners)
539 {
540 List<ListenerInfo> listeners;
541 if (!m_listeners.TryGetValue(channel,out listeners))
542 {
543 return collection;
544 }
545
546 foreach (ListenerInfo li in listeners)
547 {
548 if (!li.IsActive())
549 {
550 continue;
551 }
552 if (!itemID.Equals(UUID.Zero) && !li.GetItemID().Equals(itemID))
553 {
554 continue;
555 }
556 if (li.GetName().Length > 0 && !li.GetName().Equals(name))
557 {
558 continue;
559 }
560 if (!li.GetID().Equals(UUID.Zero) && !li.GetID().Equals(id))
561 {
562 continue;
563 }
564 if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg))
565 {
566 continue;
567 }
568 collection.Add(li);
569 }
570 }
571 return collection;
572 }
573
574 public Object[] GetSerializationData(UUID itemID)
575 {
576 List<Object> data = new List<Object>();
577
578 foreach (List<ListenerInfo> list in m_listeners.Values)
579 {
580 foreach (ListenerInfo l in list)
581 {
582 if (l.GetItemID() == itemID)
583 data.AddRange(l.GetSerializationData());
584 }
585 }
586 return (Object[])data.ToArray();
587 }
588
589 public void AddFromData(uint localID, UUID itemID, UUID hostID,
590 Object[] data)
591 {
592 int idx = 0;
593 Object[] item = new Object[6];
594
595 while (idx < data.Length)
596 {
597 Array.Copy(data, idx, item, 0, 6);
598
599 ListenerInfo info =
600 ListenerInfo.FromData(localID, itemID, hostID, item);
601
602 if (!m_listeners.ContainsKey((int)item[2]))
603 m_listeners.Add((int)item[2], new List<ListenerInfo>());
604 m_listeners[(int)item[2]].Add(info);
605
606 idx+=6;
607 }
608 }
609 }
610
611 public class ListenerInfo: IWorldCommListenerInfo
612 {
613 private bool m_active; // Listener is active or not
614 private int m_handle; // Assigned handle of this listener
615 private uint m_localID; // Local ID from script engine
616 private UUID m_itemID; // ID of the host script engine
617 private UUID m_hostID; // ID of the host/scene part
618 private int m_channel; // Channel
619 private UUID m_id; // ID to filter messages from
620 private string m_name; // Object name to filter messages from
621 private string m_message; // The message
622
623 public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message)
624 {
625 Initialise(handle, localID, ItemID, hostID, channel, name, id, message);
626 }
627
628 public ListenerInfo(ListenerInfo li, string name, UUID id, string message)
629 {
630 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message);
631 }
632
633 private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name,
634 UUID id, string message)
635 {
636 m_active = true;
637 m_handle = handle;
638 m_localID = localID;
639 m_itemID = ItemID;
640 m_hostID = hostID;
641 m_channel = channel;
642 m_name = name;
643 m_id = id;
644 m_message = message;
645 }
646
647 public Object[] GetSerializationData()
648 {
649 Object[] data = new Object[6];
650
651 data[0] = m_active;
652 data[1] = m_handle;
653 data[2] = m_channel;
654 data[3] = m_name;
655 data[4] = m_id;
656 data[5] = m_message;
657
658 return data;
659 }
660
661 public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data)
662 {
663 ListenerInfo linfo = new ListenerInfo((int)data[1], localID,
664 ItemID, hostID, (int)data[2], (string)data[3],
665 (UUID)data[4], (string)data[5]);
666 linfo.m_active=(bool)data[0];
667
668 return linfo;
669 }
670
671 public UUID GetItemID()
672 {
673 return m_itemID;
674 }
675
676 public UUID GetHostID()
677 {
678 return m_hostID;
679 }
680
681 public int GetChannel()
682 {
683 return m_channel;
684 }
685
686 public uint GetLocalID()
687 {
688 return m_localID;
689 }
690
691 public int GetHandle()
692 {
693 return m_handle;
694 }
695
696 public string GetMessage()
697 {
698 return m_message;
699 }
700
701 public string GetName()
702 {
703 return m_name;
704 }
705
706 public bool IsActive()
707 {
708 return m_active;
709 }
710
711 public void Deactivate()
712 {
713 m_active = false;
714 }
715
716 public void Activate()
717 {
718 m_active = true;
719 }
720
721 public UUID GetID()
722 {
723 return m_id;
724 }
725 }
726}
diff --git a/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs
deleted file mode 100644
index fb86731..0000000
--- a/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs
+++ /dev/null
@@ -1,726 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33using System.Threading;
34using OpenMetaverse;
35using log4net;
36using Nini.Config;
37using Nwc.XmlRpc;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42
43/*****************************************************
44 *
45 * XMLRPCModule
46 *
47 * Module for accepting incoming communications from
48 * external XMLRPC client and calling a remote data
49 * procedure for a registered data channel/prim.
50 *
51 *
52 * 1. On module load, open a listener port
53 * 2. Attach an XMLRPC handler
54 * 3. When a request is received:
55 * 3.1 Parse into components: channel key, int, string
56 * 3.2 Look up registered channel listeners
57 * 3.3 Call the channel (prim) remote data method
58 * 3.4 Capture the response (llRemoteDataReply)
59 * 3.5 Return response to client caller
60 * 3.6 If no response from llRemoteDataReply within
61 * RemoteReplyScriptTimeout, generate script timeout fault
62 *
63 * Prims in script must:
64 * 1. Open a remote data channel
65 * 1.1 Generate a channel ID
66 * 1.2 Register primid,channelid pair with module
67 * 2. Implement the remote data procedure handler
68 *
69 * llOpenRemoteDataChannel
70 * llRemoteDataReply
71 * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval)
72 * llCloseRemoteDataChannel
73 *
74 * **************************************************/
75
76namespace OpenSim.Region.Environment.Modules.Scripting.XMLRPC
77{
78 public class XMLRPCModule : IRegionModule, IXMLRPC
79 {
80 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
81
82 private string m_name = "XMLRPCModule";
83
84 // <channel id, RPCChannelInfo>
85 private Dictionary<UUID, RPCChannelInfo> m_openChannels;
86 private Dictionary<UUID, SendRemoteDataRequest> m_pendingSRDResponses;
87 private int m_remoteDataPort = 0;
88
89 private Dictionary<UUID, RPCRequestInfo> m_rpcPending;
90 private Dictionary<UUID, RPCRequestInfo> m_rpcPendingResponses;
91 private List<Scene> m_scenes = new List<Scene>();
92 private int RemoteReplyScriptTimeout = 9000;
93 private int RemoteReplyScriptWait = 300;
94 private object XMLRPCListLock = new object();
95
96 #region IRegionModule Members
97
98 public void Initialise(Scene scene, IConfigSource config)
99 {
100 // We need to create these early because the scripts might be calling
101 // But since this gets called for every region, we need to make sure they
102 // get called only one time (or we lose any open channels)
103 if (null == m_openChannels)
104 {
105 m_openChannels = new Dictionary<UUID, RPCChannelInfo>();
106 m_rpcPending = new Dictionary<UUID, RPCRequestInfo>();
107 m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>();
108 m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>();
109
110 try
111 {
112 m_remoteDataPort = config.Configs["Network"].GetInt("remoteDataPort", m_remoteDataPort);
113 }
114 catch (Exception)
115 {
116 }
117 }
118
119 if (!m_scenes.Contains(scene))
120 {
121 m_scenes.Add(scene);
122
123 scene.RegisterModuleInterface<IXMLRPC>(this);
124 }
125 }
126
127 public void PostInitialise()
128 {
129 if (IsEnabled())
130 {
131 // Start http server
132 // Attach xmlrpc handlers
133 m_log.Info("[REMOTE_DATA]: " +
134 "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands.");
135 BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort);
136 httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
137 httpServer.Start();
138 }
139 }
140
141 public void Close()
142 {
143 }
144
145 public string Name
146 {
147 get { return m_name; }
148 }
149
150 public bool IsSharedModule
151 {
152 get { return true; }
153 }
154
155 #endregion
156
157 #region IXMLRPC Members
158
159 public bool IsEnabled()
160 {
161 return (m_remoteDataPort > 0);
162 }
163
164 /**********************************************
165 * OpenXMLRPCChannel
166 *
167 * Generate a UUID channel key and add it and
168 * the prim id to dictionary <channelUUID, primUUID>
169 *
170 * A custom channel key can be proposed.
171 * Otherwise, passing UUID.Zero will generate
172 * and return a random channel
173 *
174 * First check if there is a channel assigned for
175 * this itemID. If there is, then someone called
176 * llOpenRemoteDataChannel twice. Just return the
177 * original channel. Other option is to delete the
178 * current channel and assign a new one.
179 *
180 * ********************************************/
181
182 public UUID OpenXMLRPCChannel(uint localID, UUID itemID, UUID channelID)
183 {
184 UUID newChannel = UUID.Zero;
185
186 // This should no longer happen, but the check is reasonable anyway
187 if (null == m_openChannels)
188 {
189 m_log.Warn("[RemoteDataReply] Attempt to open channel before initialization is complete");
190 return newChannel;
191 }
192
193 //Is a dupe?
194 foreach (RPCChannelInfo ci in m_openChannels.Values)
195 {
196 if (ci.GetItemID().Equals(itemID))
197 {
198 // return the original channel ID for this item
199 newChannel = ci.GetChannelID();
200 break;
201 }
202 }
203
204 if (newChannel == UUID.Zero)
205 {
206 newChannel = (channelID == UUID.Zero) ? UUID.Random() : channelID;
207 RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, newChannel);
208 lock (XMLRPCListLock)
209 {
210 m_openChannels.Add(newChannel, rpcChanInfo);
211 }
212 }
213
214 return newChannel;
215 }
216
217 // Delete channels based on itemID
218 // for when a script is deleted
219 public void DeleteChannels(UUID itemID)
220 {
221 if (m_openChannels != null)
222 {
223 ArrayList tmp = new ArrayList();
224
225 lock (XMLRPCListLock)
226 {
227 foreach (RPCChannelInfo li in m_openChannels.Values)
228 {
229 if (li.GetItemID().Equals(itemID))
230 {
231 tmp.Add(itemID);
232 }
233 }
234
235 IEnumerator tmpEnumerator = tmp.GetEnumerator();
236 while (tmpEnumerator.MoveNext())
237 m_openChannels.Remove((UUID) tmpEnumerator.Current);
238 }
239 }
240 }
241
242 /**********************************************
243 * Remote Data Reply
244 *
245 * Response to RPC message
246 *
247 *********************************************/
248
249 public void RemoteDataReply(string channel, string message_id, string sdata, int idata)
250 {
251 UUID message_key = new UUID(message_id);
252 UUID channel_key = new UUID(channel);
253
254 RPCRequestInfo rpcInfo = null;
255
256 if (message_key == UUID.Zero)
257 {
258 foreach (RPCRequestInfo oneRpcInfo in m_rpcPendingResponses.Values)
259 if (oneRpcInfo.GetChannelKey() == channel_key)
260 rpcInfo = oneRpcInfo;
261 }
262 else
263 {
264 m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo);
265 }
266
267 if (rpcInfo != null)
268 {
269 rpcInfo.SetStrRetval(sdata);
270 rpcInfo.SetIntRetval(idata);
271 rpcInfo.SetProcessed(true);
272 m_rpcPendingResponses.Remove(message_key);
273 }
274 else
275 {
276 m_log.Warn("[RemoteDataReply]: Channel or message_id not found");
277 }
278 }
279
280 /**********************************************
281 * CloseXMLRPCChannel
282 *
283 * Remove channel from dictionary
284 *
285 *********************************************/
286
287 public void CloseXMLRPCChannel(UUID channelKey)
288 {
289 if (m_openChannels.ContainsKey(channelKey))
290 m_openChannels.Remove(channelKey);
291 }
292
293
294 public bool hasRequests()
295 {
296 lock (XMLRPCListLock)
297 {
298 if (m_rpcPending != null)
299 return (m_rpcPending.Count > 0);
300 else
301 return false;
302 }
303 }
304
305 public IXmlRpcRequestInfo GetNextCompletedRequest()
306 {
307 if (m_rpcPending != null)
308 {
309 lock (XMLRPCListLock)
310 {
311 foreach (UUID luid in m_rpcPending.Keys)
312 {
313 RPCRequestInfo tmpReq;
314
315 if (m_rpcPending.TryGetValue(luid, out tmpReq))
316 {
317 if (!tmpReq.IsProcessed()) return tmpReq;
318 }
319 }
320 }
321 }
322 return null;
323 }
324
325 public void RemoveCompletedRequest(UUID id)
326 {
327 lock (XMLRPCListLock)
328 {
329 RPCRequestInfo tmp;
330 if (m_rpcPending.TryGetValue(id, out tmp))
331 {
332 m_rpcPending.Remove(id);
333 m_rpcPendingResponses.Add(id, tmp);
334 }
335 else
336 {
337 Console.WriteLine("UNABLE TO REMOVE COMPLETED REQUEST");
338 }
339 }
340 }
341
342 public UUID SendRemoteData(uint localID, UUID itemID, string channel, string dest, int idata, string sdata)
343 {
344 SendRemoteDataRequest req = new SendRemoteDataRequest(
345 localID, itemID, channel, dest, idata, sdata
346 );
347 m_pendingSRDResponses.Add(req.GetReqID(), req);
348 req.Process();
349 return req.ReqID;
350 }
351
352 public IServiceRequest GetNextCompletedSRDRequest()
353 {
354 if (m_pendingSRDResponses != null)
355 {
356 lock (XMLRPCListLock)
357 {
358 foreach (UUID luid in m_pendingSRDResponses.Keys)
359 {
360 SendRemoteDataRequest tmpReq;
361
362 if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq))
363 {
364 if (tmpReq.Finished)
365 return tmpReq;
366 }
367 }
368 }
369 }
370 return null;
371 }
372
373 public void RemoveCompletedSRDRequest(UUID id)
374 {
375 lock (XMLRPCListLock)
376 {
377 SendRemoteDataRequest tmpReq;
378 if (m_pendingSRDResponses.TryGetValue(id, out tmpReq))
379 {
380 m_pendingSRDResponses.Remove(id);
381 }
382 }
383 }
384
385 public void CancelSRDRequests(UUID itemID)
386 {
387 if (m_pendingSRDResponses != null)
388 {
389 lock (XMLRPCListLock)
390 {
391 foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values)
392 {
393 if (li.ItemID.Equals(itemID))
394 m_pendingSRDResponses.Remove(li.GetReqID());
395 }
396 }
397 }
398 }
399
400 #endregion
401
402 public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request)
403 {
404 XmlRpcResponse response = new XmlRpcResponse();
405
406 Hashtable requestData = (Hashtable) request.Params[0];
407 bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") &&
408 requestData.Contains("StringValue"));
409
410 if (GoodXML)
411 {
412 UUID channel = new UUID((string) requestData["Channel"]);
413 RPCChannelInfo rpcChanInfo;
414 if (m_openChannels.TryGetValue(channel, out rpcChanInfo))
415 {
416 string intVal = Convert.ToInt32(requestData["IntValue"]).ToString();
417 string strVal = (string) requestData["StringValue"];
418
419 RPCRequestInfo rpcInfo;
420
421 lock (XMLRPCListLock)
422 {
423 rpcInfo =
424 new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal,
425 intVal);
426 m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo);
427 }
428
429 int timeoutCtr = 0;
430
431 while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout))
432 {
433 Thread.Sleep(RemoteReplyScriptWait);
434 timeoutCtr += RemoteReplyScriptWait;
435 }
436 if (rpcInfo.IsProcessed())
437 {
438 Hashtable param = new Hashtable();
439 param["StringValue"] = rpcInfo.GetStrRetval();
440 param["IntValue"] = rpcInfo.GetIntRetval();
441
442 ArrayList parameters = new ArrayList();
443 parameters.Add(param);
444
445 response.Value = parameters;
446 rpcInfo = null;
447 }
448 else
449 {
450 response.SetFault(-1, "Script timeout");
451 rpcInfo = null;
452 }
453 }
454 else
455 {
456 response.SetFault(-1, "Invalid channel");
457 }
458 }
459
460 return response;
461 }
462 }
463
464 public class RPCRequestInfo: IXmlRpcRequestInfo
465 {
466 private UUID m_ChannelKey;
467 private string m_IntVal;
468 private UUID m_ItemID;
469 private uint m_localID;
470 private UUID m_MessageID;
471 private bool m_processed;
472 private int m_respInt;
473 private string m_respStr;
474 private string m_StrVal;
475
476 public RPCRequestInfo(uint localID, UUID itemID, UUID channelKey, string strVal, string intVal)
477 {
478 m_localID = localID;
479 m_StrVal = strVal;
480 m_IntVal = intVal;
481 m_ItemID = itemID;
482 m_ChannelKey = channelKey;
483 m_MessageID = UUID.Random();
484 m_processed = false;
485 m_respStr = String.Empty;
486 m_respInt = 0;
487 }
488
489 public bool IsProcessed()
490 {
491 return m_processed;
492 }
493
494 public UUID GetChannelKey()
495 {
496 return m_ChannelKey;
497 }
498
499 public void SetProcessed(bool processed)
500 {
501 m_processed = processed;
502 }
503
504 public void SetStrRetval(string resp)
505 {
506 m_respStr = resp;
507 }
508
509 public string GetStrRetval()
510 {
511 return m_respStr;
512 }
513
514 public void SetIntRetval(int resp)
515 {
516 m_respInt = resp;
517 }
518
519 public int GetIntRetval()
520 {
521 return m_respInt;
522 }
523
524 public uint GetLocalID()
525 {
526 return m_localID;
527 }
528
529 public UUID GetItemID()
530 {
531 return m_ItemID;
532 }
533
534 public string GetStrVal()
535 {
536 return m_StrVal;
537 }
538
539 public int GetIntValue()
540 {
541 return int.Parse(m_IntVal);
542 }
543
544 public UUID GetMessageID()
545 {
546 return m_MessageID;
547 }
548 }
549
550 public class RPCChannelInfo
551 {
552 private UUID m_ChannelKey;
553 private UUID m_itemID;
554 private uint m_localID;
555
556 public RPCChannelInfo(uint localID, UUID itemID, UUID channelID)
557 {
558 m_ChannelKey = channelID;
559 m_localID = localID;
560 m_itemID = itemID;
561 }
562
563 public UUID GetItemID()
564 {
565 return m_itemID;
566 }
567
568 public UUID GetChannelID()
569 {
570 return m_ChannelKey;
571 }
572
573 public uint GetLocalID()
574 {
575 return m_localID;
576 }
577 }
578
579 public class SendRemoteDataRequest: IServiceRequest
580 {
581 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
582
583 public string Channel;
584 public string DestURL;
585 private bool _finished;
586 public bool Finished
587 {
588 get { return _finished; }
589 set { _finished = value; }
590 }
591 private Thread httpThread;
592 public int Idata;
593 private UUID _itemID;
594 public UUID ItemID
595 {
596 get { return _itemID; }
597 set { _itemID = value; }
598 }
599 private uint _localID;
600 public uint LocalID
601 {
602 get { return _localID; }
603 set { _localID = value; }
604 }
605 private UUID _reqID;
606 public UUID ReqID
607 {
608 get { return _reqID; }
609 set { _reqID = value; }
610 }
611 public XmlRpcRequest Request;
612 public int ResponseIdata;
613 public string ResponseSdata;
614 public string Sdata;
615
616 public SendRemoteDataRequest(uint localID, UUID itemID, string channel, string dest, int idata, string sdata)
617 {
618 this.Channel = channel;
619 DestURL = dest;
620 this.Idata = idata;
621 this.Sdata = sdata;
622 ItemID = itemID;
623 LocalID = localID;
624
625 ReqID = UUID.Random();
626 }
627
628 public void Process()
629 {
630 httpThread = new Thread(SendRequest);
631 httpThread.Name = "HttpRequestThread";
632 httpThread.Priority = ThreadPriority.BelowNormal;
633 httpThread.IsBackground = true;
634 _finished = false;
635 httpThread.Start();
636 ThreadTracker.Add(httpThread);
637 }
638
639 /*
640 * TODO: More work on the response codes. Right now
641 * returning 200 for success or 499 for exception
642 */
643
644 public void SendRequest()
645 {
646 Hashtable param = new Hashtable();
647
648 // Check if channel is an UUID
649 // if not, use as method name
650 UUID parseUID;
651 string mName = "llRemoteData";
652 if ((Channel != null) && (Channel != ""))
653 if (!UUID.TryParse(Channel, out parseUID))
654 mName = Channel;
655 else
656 param["Channel"] = Channel;
657
658 param["StringValue"] = Sdata;
659 param["IntValue"] = Convert.ToString(Idata);
660
661 ArrayList parameters = new ArrayList();
662 parameters.Add(param);
663 XmlRpcRequest req = new XmlRpcRequest(mName, parameters);
664 try
665 {
666 XmlRpcResponse resp = req.Send(DestURL, 30000);
667 if (resp != null)
668 {
669 Hashtable respParms;
670 if (resp.Value.GetType().Equals(typeof(System.Collections.Hashtable)))
671 {
672 respParms = (Hashtable) resp.Value;
673 }
674 else
675 {
676 ArrayList respData = (ArrayList) resp.Value;
677 respParms = (Hashtable) respData[0];
678 }
679 if (respParms != null)
680 {
681 if (respParms.Contains("StringValue"))
682 {
683 Sdata = (string) respParms["StringValue"];
684 }
685 if (respParms.Contains("IntValue"))
686 {
687 Idata = Convert.ToInt32((string) respParms["IntValue"]);
688 }
689 if (respParms.Contains("faultString"))
690 {
691 Sdata = (string) respParms["faultString"];
692 }
693 if (respParms.Contains("faultCode"))
694 {
695 Idata = Convert.ToInt32(respParms["faultCode"]);
696 }
697 }
698 }
699 }
700 catch (Exception we)
701 {
702 Sdata = we.Message;
703 m_log.Warn("[SendRemoteDataRequest]: Request failed");
704 m_log.Warn(we.StackTrace);
705 }
706
707 _finished = true;
708 }
709
710 public void Stop()
711 {
712 try
713 {
714 httpThread.Abort();
715 }
716 catch (Exception)
717 {
718 }
719 }
720
721 public UUID GetReqID()
722 {
723 return ReqID;
724 }
725 }
726}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs
deleted file mode 100644
index 4151c88..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs
+++ /dev/null
@@ -1,128 +0,0 @@
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 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 */
27
28using System.Collections.Generic;
29using OpenMetaverse;
30
31namespace OpenSim.Region.Environment.Modules.World.Archiver
32{
33 /// <summary>
34 /// Constants for the archiving module
35 /// </summary>
36 public class ArchiveConstants
37 {
38 /// <summary>
39 /// The location of the archive control file
40 /// </summary>
41 public static readonly string CONTROL_FILE_PATH = "archive.xml";
42
43 /// <summary>
44 /// Path for the assets held in an archive
45 /// </summary>
46 public static readonly string ASSETS_PATH = "assets/";
47
48 /// <summary>
49 /// Path for the assets metadata file
50 /// </summary>
51 //public static readonly string ASSETS_METADATA_PATH = "assets.xml";
52
53 /// <summary>
54 /// Path for the prims file
55 /// </summary>
56 public static readonly string OBJECTS_PATH = "objects/";
57
58 /// <summary>
59 /// Path for terrains. Technically these may be assets, but I think it's quite nice to split them out.
60 /// </summary>
61 public static readonly string TERRAINS_PATH = "terrains/";
62
63 /// <summary>
64 /// Path for region settings.
65 /// </summary>
66 public static readonly string SETTINGS_PATH = "settings/";
67
68 /// <summary>
69 /// The character the separates the uuid from extension information in an archived asset filename
70 /// </summary>
71 public static readonly string ASSET_EXTENSION_SEPARATOR = "_";
72
73 /// <summary>
74 /// Extensions used for asset types in the archive
75 /// </summary>
76 public static readonly IDictionary<sbyte, string> ASSET_TYPE_TO_EXTENSION = new Dictionary<sbyte, string>();
77 public static readonly IDictionary<string, sbyte> EXTENSION_TO_ASSET_TYPE = new Dictionary<string, sbyte>();
78
79 static ArchiveConstants()
80 {
81 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Animation] = ASSET_EXTENSION_SEPARATOR + "animation.bvh";
82 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Bodypart] = ASSET_EXTENSION_SEPARATOR + "bodypart.txt";
83 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.CallingCard] = ASSET_EXTENSION_SEPARATOR + "callingcard.txt";
84 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Clothing] = ASSET_EXTENSION_SEPARATOR + "clothing.txt";
85 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Folder] = ASSET_EXTENSION_SEPARATOR + "folder.txt"; // Not sure if we'll ever see this
86 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Gesture] = ASSET_EXTENSION_SEPARATOR + "gesture.txt";
87 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.ImageJPEG] = ASSET_EXTENSION_SEPARATOR + "image.jpg";
88 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.ImageTGA] = ASSET_EXTENSION_SEPARATOR + "image.tga";
89 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Landmark] = ASSET_EXTENSION_SEPARATOR + "landmark.txt";
90 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LostAndFoundFolder] = ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"; // Not sure if we'll ever see this
91 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLBytecode] = ASSET_EXTENSION_SEPARATOR + "bytecode.lso";
92 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLText] = ASSET_EXTENSION_SEPARATOR + "script.lsl";
93 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Notecard] = ASSET_EXTENSION_SEPARATOR + "notecard.txt";
94 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Object] = ASSET_EXTENSION_SEPARATOR + "object.xml";
95 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.RootFolder] = ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"; // Not sure if we'll ever see this
96 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Simstate] = ASSET_EXTENSION_SEPARATOR + "simstate.bin"; // Not sure if we'll ever see this
97 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SnapshotFolder] = ASSET_EXTENSION_SEPARATOR + "snapshotfolder.txt"; // Not sure if we'll ever see this
98 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Sound] = ASSET_EXTENSION_SEPARATOR + "sound.ogg";
99 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV] = ASSET_EXTENSION_SEPARATOR + "sound.wav";
100 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2";
101 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga";
102 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this
103
104 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation;
105 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart;
106 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "callingcard.txt"] = (sbyte)AssetType.CallingCard;
107 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "clothing.txt"] = (sbyte)AssetType.Clothing;
108 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "folder.txt"] = (sbyte)AssetType.Folder;
109 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "gesture.txt"] = (sbyte)AssetType.Gesture;
110 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "image.jpg"] = (sbyte)AssetType.ImageJPEG;
111 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "image.tga"] = (sbyte)AssetType.ImageTGA;
112 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "landmark.txt"] = (sbyte)AssetType.Landmark;
113 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"] = (sbyte)AssetType.LostAndFoundFolder;
114 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bytecode.lso"] = (sbyte)AssetType.LSLBytecode;
115 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "script.lsl"] = (sbyte)AssetType.LSLText;
116 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "notecard.txt"] = (sbyte)AssetType.Notecard;
117 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "object.xml"] = (sbyte)AssetType.Object;
118 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"] = (sbyte)AssetType.RootFolder;
119 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "simstate.bin"] = (sbyte)AssetType.Simstate;
120 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "snapshotfolder.txt"] = (sbyte)AssetType.SnapshotFolder;
121 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "sound.ogg"] = (sbyte)AssetType.Sound;
122 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "sound.wav"] = (sbyte)AssetType.SoundWAV;
123 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture;
124 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA;
125 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder;
126 }
127 }
128}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs
deleted file mode 100644
index b507c52..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs
+++ /dev/null
@@ -1,460 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.IO.Compression;
32using System.Reflection;
33using System.Xml;
34using System.Net;
35using OpenMetaverse;
36using log4net;
37using OpenSim.Framework;
38using OpenSim.Framework.Communications.Cache;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Environment.Modules.World.Terrain;
42
43namespace OpenSim.Region.Environment.Modules.World.Archiver
44{
45 /// <summary>
46 /// Handles an individual archive read request
47 /// </summary>
48 public class ArchiveReadRequest
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding();
53
54 private Scene m_scene;
55 private Stream m_loadStream;
56 private string m_errorMessage;
57
58 /// <summary>
59 /// Used to cache lookups for valid uuids.
60 /// </summary>
61 private IDictionary<UUID, bool> m_validUserUuids = new Dictionary<UUID, bool>();
62
63 public ArchiveReadRequest(Scene scene, string loadPath)
64 {
65 m_scene = scene;
66 m_loadStream = new GZipStream(GetStream(loadPath), CompressionMode.Decompress);
67 m_errorMessage = String.Empty;
68 }
69
70 public ArchiveReadRequest(Scene scene, Stream loadStream)
71 {
72 m_scene = scene;
73 m_loadStream = loadStream;
74 }
75
76 /// <summary>
77 /// Dearchive the region embodied in this request.
78 /// </summary>
79 public void DearchiveRegion()
80 {
81 // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions
82 DearchiveRegion0DotStar();
83 }
84
85 private void DearchiveRegion0DotStar()
86 {
87 int successfulAssetRestores = 0;
88 int failedAssetRestores = 0;
89 List<string> serialisedSceneObjects = new List<string>();
90
91 try
92 {
93 TarArchiveReader archive = new TarArchiveReader(m_loadStream);
94
95 //AssetsDearchiver dearchiver = new AssetsDearchiver(m_scene.AssetCache);
96
97 string filePath = "ERROR";
98
99 byte[] data;
100 TarArchiveReader.TarEntryType entryType;
101
102 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
103 {
104 //m_log.DebugFormat(
105 // "[ARCHIVER]: Successfully read {0} ({1} bytes)}", filePath, data.Length);
106 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
107 {
108 m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}",
109 filePath);
110 }
111 else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
112 {
113 serialisedSceneObjects.Add(m_asciiEncoding.GetString(data));
114 }
115// else if (filePath.Equals(ArchiveConstants.ASSETS_METADATA_PATH))
116// {
117// string xml = m_asciiEncoding.GetString(data);
118// dearchiver.AddAssetMetadata(xml);
119// }
120 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
121 {
122 if (LoadAsset(filePath, data))
123 successfulAssetRestores++;
124 else
125 failedAssetRestores++;
126 }
127 else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
128 {
129 LoadTerrain(filePath, data);
130 }
131 else if (filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
132 {
133 LoadRegionSettings(filePath, data);
134 }
135 }
136
137 //m_log.Debug("[ARCHIVER]: Reached end of archive");
138
139 archive.Close();
140 }
141 catch (Exception e)
142 {
143 m_log.ErrorFormat(
144 "[ARCHIVER]: Error loading oar file. Exception was: {0}", e);
145 m_errorMessage += e.ToString();
146 m_scene.EventManager.TriggerOarFileLoaded(m_errorMessage);
147 return;
148 }
149
150 m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores);
151
152 if (failedAssetRestores > 0)
153 {
154 m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores);
155 m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores);
156 }
157
158 m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
159 m_scene.DeleteAllSceneObjects();
160
161 // Reload serialized prims
162 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
163
164 IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>();
165 ICollection<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
166
167 foreach (string serialisedSceneObject in serialisedSceneObjects)
168 {
169 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
170
171 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
172 // on the same region server and multiple examples a single object archive to be imported
173 // to the same scene (when this is possible).
174 sceneObject.ResetIDs();
175
176 // Try to retain the original creator/owner/lastowner if their uuid is present on this grid
177 // otherwise, use the master avatar uuid instead
178 UUID masterAvatarId = m_scene.RegionInfo.MasterAvatarAssignedUUID;
179
180 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
181 masterAvatarId = m_scene.RegionInfo.EstateSettings.EstateOwner;
182
183 foreach (SceneObjectPart part in sceneObject.Children.Values)
184 {
185 if (!resolveUserUuid(part.CreatorID))
186 part.CreatorID = masterAvatarId;
187
188 if (!resolveUserUuid(part.OwnerID))
189 part.OwnerID = masterAvatarId;
190
191 if (!resolveUserUuid(part.LastOwnerID))
192 part.LastOwnerID = masterAvatarId;
193
194 // And zap any troublesome sit target information
195 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
196 part.SitTargetPosition = new Vector3(0, 0, 0);
197
198 // Fix ownership/creator of inventory items
199 // Not doing so results in inventory items
200 // being no copy/no mod for everyone
201 TaskInventoryDictionary inv = part.TaskInventory;
202 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
203 {
204 if (!resolveUserUuid(kvp.Value.OwnerID))
205 {
206 kvp.Value.OwnerID = masterAvatarId;
207 }
208 if (!resolveUserUuid(kvp.Value.CreatorID))
209 {
210 kvp.Value.CreatorID = masterAvatarId;
211 }
212 }
213 }
214
215 if (m_scene.AddRestoredSceneObject(sceneObject, true, false))
216 {
217 sceneObjects.Add(sceneObject);
218 }
219 }
220
221 m_log.InfoFormat("[ARCHIVER]: Restored {0} scene objects to the scene", sceneObjects.Count);
222
223 int ignoredObjects = serialisedSceneObjects.Count - sceneObjects.Count;
224
225 if (ignoredObjects > 0)
226 m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects);
227
228 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
229
230 m_log.Debug("[ARCHIVER]: Starting scripts");
231
232 foreach (SceneObjectGroup sceneObject in sceneObjects)
233 {
234 sceneObject.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 0);
235 }
236
237 m_scene.EventManager.TriggerOarFileLoaded(m_errorMessage);
238 }
239
240 /// <summary>
241 /// Look up the given user id to check whether it's one that is valid for this grid.
242 /// </summary>
243 /// <param name="uuid"></param>
244 /// <returns></returns>
245 private bool resolveUserUuid(UUID uuid)
246 {
247 if (!m_validUserUuids.ContainsKey(uuid))
248 {
249 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(uuid);
250 if (profile != null && profile.UserProfile != null)
251 m_validUserUuids.Add(uuid, true);
252 else
253 m_validUserUuids.Add(uuid, false);
254 }
255
256 if (m_validUserUuids[uuid])
257 return true;
258 else
259 return false;
260 }
261
262 /// <summary>
263 /// Load an asset
264 /// </summary>
265 /// <param name="assetFilename"></param>
266 /// <param name="data"></param>
267 /// <returns>true if asset was successfully loaded, false otherwise</returns>
268 private bool LoadAsset(string assetPath, byte[] data)
269 {
270 // Right now we're nastily obtaining the UUID from the filename
271 string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
272 int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
273
274 if (i == -1)
275 {
276 m_log.ErrorFormat(
277 "[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping",
278 assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
279
280 return false;
281 }
282
283 string extension = filename.Substring(i);
284 string uuid = filename.Remove(filename.Length - extension.Length);
285
286 if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
287 {
288 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
289
290 //m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
291
292 AssetBase asset = new AssetBase(new UUID(uuid), String.Empty);
293 asset.Metadata.Type = assetType;
294 asset.Data = data;
295
296 m_scene.AssetCache.AddAsset(asset);
297
298 /**
299 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so
300 * it might be best done when dearchive takes place on a separate thread
301 if (asset.Type=AssetType.Texture)
302 {
303 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
304 if (cacheLayerDecode != null)
305 cacheLayerDecode.syncdecode(asset.FullID, asset.Data);
306 }
307 */
308
309 return true;
310 }
311 else
312 {
313 m_log.ErrorFormat(
314 "[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
315 assetPath, extension);
316
317 return false;
318 }
319 }
320
321 /// <summary>
322 /// Load region settings data
323 /// </summary>
324 /// <param name="settingsPath"></param>
325 /// <param name="data"></param>
326 /// <returns>
327 /// true if settings were loaded successfully, false otherwise
328 /// </returns>
329 private bool LoadRegionSettings(string settingsPath, byte[] data)
330 {
331 RegionSettings loadedRegionSettings;
332
333 try
334 {
335 loadedRegionSettings = RegionSettingsSerializer.Deserialize(data);
336 }
337 catch (Exception e)
338 {
339 m_log.ErrorFormat(
340 "[ARCHIVER]: Could not parse region settings file {0}. Ignoring. Exception was {1}",
341 settingsPath, e);
342 return false;
343 }
344
345 RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings;
346
347 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit;
348 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage;
349 currentRegionSettings.AllowLandJoinDivide = loadedRegionSettings.AllowLandJoinDivide;
350 currentRegionSettings.AllowLandResell = loadedRegionSettings.AllowLandResell;
351 currentRegionSettings.BlockFly = loadedRegionSettings.BlockFly;
352 currentRegionSettings.BlockShowInSearch = loadedRegionSettings.BlockShowInSearch;
353 currentRegionSettings.BlockTerraform = loadedRegionSettings.BlockTerraform;
354 currentRegionSettings.DisableCollisions = loadedRegionSettings.DisableCollisions;
355 currentRegionSettings.DisablePhysics = loadedRegionSettings.DisablePhysics;
356 currentRegionSettings.DisableScripts = loadedRegionSettings.DisableScripts;
357 currentRegionSettings.Elevation1NE = loadedRegionSettings.Elevation1NE;
358 currentRegionSettings.Elevation1NW = loadedRegionSettings.Elevation1NW;
359 currentRegionSettings.Elevation1SE = loadedRegionSettings.Elevation1SE;
360 currentRegionSettings.Elevation1SW = loadedRegionSettings.Elevation1SW;
361 currentRegionSettings.Elevation2NE = loadedRegionSettings.Elevation2NE;
362 currentRegionSettings.Elevation2NW = loadedRegionSettings.Elevation2NW;
363 currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE;
364 currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW;
365 currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun;
366 currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus;
367 currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing;
368 currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit;
369 currentRegionSettings.TerrainRaiseLimit = loadedRegionSettings.TerrainRaiseLimit;
370 currentRegionSettings.TerrainTexture1 = loadedRegionSettings.TerrainTexture1;
371 currentRegionSettings.TerrainTexture2 = loadedRegionSettings.TerrainTexture2;
372 currentRegionSettings.TerrainTexture3 = loadedRegionSettings.TerrainTexture3;
373 currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4;
374 currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun;
375 currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight;
376
377 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
378 estateModule.sendRegionHandshakeToAll();
379
380 return true;
381 }
382
383 /// <summary>
384 /// Load terrain data
385 /// </summary>
386 /// <param name="terrainPath"></param>
387 /// <param name="data"></param>
388 /// <returns>
389 /// true if terrain was resolved successfully, false otherwise.
390 /// </returns>
391 private bool LoadTerrain(string terrainPath, byte[] data)
392 {
393 ITerrainModule terrainModule = m_scene.RequestModuleInterface<ITerrainModule>();
394
395 MemoryStream ms = new MemoryStream(data);
396 terrainModule.LoadFromStream(terrainPath, ms);
397 ms.Close();
398
399 m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath);
400
401 return true;
402 }
403
404 /// <summary>
405 /// Resolve path to a working FileStream
406 /// </summary>
407 private Stream GetStream(string path)
408 {
409 try
410 {
411 if (File.Exists(path))
412 {
413 return new FileStream(path, FileMode.Open);
414 }
415 else
416 {
417 Uri uri = new Uri(path); // throw exception if not valid URI
418 if (uri.Scheme == "file")
419 {
420 return new FileStream(uri.AbsolutePath, FileMode.Open);
421 }
422 else
423 {
424 if (uri.Scheme != "http")
425 throw new Exception(String.Format("Unsupported URI scheme ({0})", path));
426
427 // OK, now we know we have an HTTP URI to work with
428
429 return URIFetch(uri);
430 }
431 }
432 }
433 catch (Exception e)
434 {
435 throw new Exception(String.Format("Unable to create file input stream for {0}: {1}", path, e));
436 }
437 }
438
439 private static Stream URIFetch(Uri uri)
440 {
441 HttpWebRequest request = (HttpWebRequest) WebRequest.Create(uri);
442
443 // request.Credentials = credentials;
444
445 request.ContentLength = 0;
446
447 WebResponse response = request.GetResponse();
448 Stream file = response.GetResponseStream();
449
450 if (response.ContentType != "application/x-oar")
451 throw new Exception(String.Format("{0} does not identify an OAR file", uri.ToString()));
452
453 if (response.ContentLength == 0)
454 throw new Exception(String.Format("{0} returned an empty file", uri.ToString()));
455
456 // return new BufferedStream(file, (int) response.ContentLength);
457 return new BufferedStream(file, 1000000);
458 }
459 }
460}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs
deleted file mode 100644
index 9a06bf7..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs
+++ /dev/null
@@ -1,161 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Xml;
33using OpenMetaverse;
34using log4net;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Region.Environment.Modules.World.Serialiser;
39using OpenSim.Region.Environment.Modules.World.Terrain;
40
41namespace OpenSim.Region.Environment.Modules.World.Archiver
42{
43 /// <summary>
44 /// Method called when all the necessary assets for an archive request have been received.
45 /// </summary>
46 public delegate void AssetsRequestCallback(IDictionary<UUID, AssetBase> assetsFound, ICollection<UUID> assetsNotFoundUuids);
47
48 /// <summary>
49 /// Execute the write of an archive once we have received all the necessary data
50 /// </summary>
51 public class ArchiveWriteRequestExecution
52 {
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 protected ITerrainModule m_terrainModule;
56 protected IRegionSerialiserModule m_serialiser;
57 protected List<SceneObjectGroup> m_sceneObjects;
58 protected Scene m_scene;
59 protected Stream m_saveStream;
60
61 public ArchiveWriteRequestExecution(
62 List<SceneObjectGroup> sceneObjects,
63 ITerrainModule terrainModule,
64 IRegionSerialiserModule serialiser,
65 Scene scene,
66 Stream saveStream)
67 {
68 m_sceneObjects = sceneObjects;
69 m_terrainModule = terrainModule;
70 m_serialiser = serialiser;
71 m_scene = scene;
72 m_saveStream = saveStream;
73 }
74
75 protected internal void ReceivedAllAssets(
76 IDictionary<UUID, AssetBase> assetsFound, ICollection<UUID> assetsNotFoundUuids)
77 {
78 foreach (UUID uuid in assetsNotFoundUuids)
79 {
80 m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid);
81 }
82
83 m_log.InfoFormat(
84 "[ARCHIVER]: Received {0} of {1} assets requested",
85 assetsFound.Count, assetsFound.Count + assetsNotFoundUuids.Count);
86
87 m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time.");
88
89 TarArchiveWriter archive = new TarArchiveWriter();
90
91 // Write out control file
92 archive.AddFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile());
93
94 // Write out region settings
95 string settingsPath
96 = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName);
97 archive.AddFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings));
98
99 // Write out terrain
100 string terrainPath
101 = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName);
102
103 MemoryStream ms = new MemoryStream();
104 m_terrainModule.SaveToStream(terrainPath, ms);
105 archive.AddFile(terrainPath, ms.ToArray());
106 ms.Close();
107
108 // Write out scene object metadata
109 foreach (SceneObjectGroup sceneObject in m_sceneObjects)
110 {
111 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
112
113 Vector3 position = sceneObject.AbsolutePosition;
114
115 string serializedObject = m_serialiser.SaveGroupToXml2(sceneObject);
116 string filename
117 = string.Format(
118 "{0}{1}_{2:000}-{3:000}-{4:000}__{5}.xml",
119 ArchiveConstants.OBJECTS_PATH, sceneObject.Name,
120 Math.Round(position.X), Math.Round(position.Y), Math.Round(position.Z),
121 sceneObject.UUID);
122
123 archive.AddFile(filename, serializedObject);
124 }
125
126 // Write out assets
127 AssetsArchiver assetsArchiver = new AssetsArchiver(assetsFound);
128 assetsArchiver.Archive(archive);
129
130 archive.WriteTar(m_saveStream);
131
132 m_log.InfoFormat("[ARCHIVER]: Wrote out OpenSimulator archive for {0}", m_scene.RegionInfo.RegionName);
133
134 m_scene.EventManager.TriggerOarFileSaved(String.Empty);
135 }
136
137 /// <summary>
138 /// Create the control file for a 0.2 version archive
139 /// </summary>
140 /// <returns></returns>
141 public static string Create0p2ControlFile()
142 {
143 StringWriter sw = new StringWriter();
144 XmlTextWriter xtw = new XmlTextWriter(sw);
145 xtw.Formatting = Formatting.Indented;
146 xtw.WriteStartDocument();
147 xtw.WriteStartElement("archive");
148 xtw.WriteAttributeString("major_version", "0");
149 xtw.WriteAttributeString("minor_version", "2");
150 xtw.WriteEndElement();
151
152 xtw.Flush();
153 xtw.Close();
154
155 String s = sw.ToString();
156 sw.Close();
157
158 return s;
159 }
160 }
161}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs
deleted file mode 100644
index 56604d6..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs
+++ /dev/null
@@ -1,333 +0,0 @@
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 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 */
27
28using OpenSim.Framework;
29using OpenSim.Framework.Communications.Cache;
30using OpenSim.Region.Framework.Interfaces;
31using OpenSim.Region.Framework.Scenes;
32using OpenSim.Region.Environment.Modules.World.Serialiser;
33using OpenSim.Region.Environment.Modules.World.Terrain;
34using System;
35using System.Collections.Generic;
36using System.IO;
37using System.IO.Compression;
38using System.Reflection;
39using System.Text.RegularExpressions;
40using System.Threading;
41using OpenMetaverse;
42using log4net;
43using Nini.Config;
44
45namespace OpenSim.Region.Environment.Modules.World.Archiver
46{
47 /// <summary>
48 /// Prepare to write out an archive.
49 /// </summary>
50 public class ArchiveWriteRequestPreparation
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 protected Scene m_scene;
55 protected Stream m_saveStream;
56
57 /// <summary>
58 /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate
59 /// asset was found by the asset service.
60 /// </summary>
61 protected AssetBase m_requestedObjectAsset;
62
63 /// <summary>
64 /// Signal whether we are currently waiting for the asset service to deliver an asset.
65 /// </summary>
66 protected bool m_waitingForObjectAsset;
67
68 /// <summary>
69 /// Constructor
70 /// </summary>
71 public ArchiveWriteRequestPreparation(Scene scene, string savePath)
72 {
73 m_scene = scene;
74 m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress);
75 }
76
77 /// <summary>
78 /// Constructor.
79 /// </summary>
80 /// <param name="scene"></param>
81 /// <param name="saveStream">The stream to which to save data.</param>
82 public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream)
83 {
84 m_scene = scene;
85 m_saveStream = saveStream;
86 }
87
88 /// <summary>
89 /// The callback made when we request the asset for an object from the asset service.
90 /// </summary>
91 public void AssetRequestCallback(UUID assetID, AssetBase asset)
92 {
93 lock (this)
94 {
95 m_requestedObjectAsset = asset;
96 m_waitingForObjectAsset = false;
97 Monitor.Pulse(this);
98 }
99 }
100
101 /// <summary>
102 /// Get an asset synchronously, potentially using an asynchronous callback. If the
103 /// asynchronous callback is used, we will wait for it to complete.
104 /// </summary>
105 /// <param name="uuid"></param>
106 /// <returns></returns>
107 protected AssetBase GetAsset(UUID uuid)
108 {
109 m_waitingForObjectAsset = true;
110 m_scene.AssetCache.GetAsset(uuid, AssetRequestCallback, true);
111
112 // The asset cache callback can either
113 //
114 // 1. Complete on the same thread (if the asset is already in the cache) or
115 // 2. Come in via a different thread (if we need to go fetch it).
116 //
117 // The code below handles both these alternatives.
118 lock (this)
119 {
120 if (m_waitingForObjectAsset)
121 {
122 Monitor.Wait(this);
123 m_waitingForObjectAsset = false;
124 }
125 }
126
127 return m_requestedObjectAsset;
128 }
129
130 /// <summary>
131 /// Record the asset uuids embedded within the given script.
132 /// </summary>
133 /// <param name="scriptUuid"></param>
134 /// <param name="assetUuids">Dictionary in which to record the references</param>
135 protected void GetScriptAssetUuids(UUID scriptUuid, IDictionary<UUID, int> assetUuids)
136 {
137 AssetBase scriptAsset = GetAsset(scriptUuid);
138
139 if (null != scriptAsset)
140 {
141 string script = Utils.BytesToString(scriptAsset.Data);
142 //m_log.DebugFormat("[ARCHIVER]: Script {0}", script);
143 MatchCollection uuidMatches = Util.UUIDPattern.Matches(script);
144 //m_log.DebugFormat("[ARCHIVER]: Found {0} matches in script", uuidMatches.Count);
145
146 foreach (Match uuidMatch in uuidMatches)
147 {
148 UUID uuid = new UUID(uuidMatch.Value);
149 //m_log.DebugFormat("[ARCHIVER]: Recording {0} in script", uuid);
150 assetUuids[uuid] = 1;
151 }
152 }
153 }
154
155 /// <summary>
156 /// Record the uuids referenced by the given wearable asset
157 /// </summary>
158 /// <param name="wearableAssetUuid"></param>
159 /// <param name="assetUuids">Dictionary in which to record the references</param>
160 protected void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, int> assetUuids)
161 {
162 AssetBase assetBase = GetAsset(wearableAssetUuid);
163 //m_log.Debug(new System.Text.ASCIIEncoding().GetString(bodypartAsset.Data));
164 AssetWearable wearableAsset = new AssetBodypart(wearableAssetUuid, assetBase.Data);
165 wearableAsset.Decode();
166
167 //m_log.DebugFormat(
168 // "[ARCHIVER]: Wearable asset {0} references {1} assets", wearableAssetUuid, wearableAsset.Textures.Count);
169
170 foreach (UUID uuid in wearableAsset.Textures.Values)
171 {
172 //m_log.DebugFormat("[ARCHIVER]: Got bodypart uuid {0}", uuid);
173 assetUuids[uuid] = 1;
174 }
175 }
176
177 /// <summary>
178 /// Get all the asset uuids associated with a given object. This includes both those directly associated with
179 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
180 /// within this object).
181 /// </summary>
182 /// <param name="sceneObject"></param>
183 /// <param name="assetUuids"></param>
184 protected void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, int> assetUuids)
185 {
186 AssetBase objectAsset = GetAsset(sceneObjectUuid);
187
188 if (null != objectAsset)
189 {
190 string xml = Utils.BytesToString(objectAsset.Data);
191 SceneObjectGroup sog = new SceneObjectGroup(xml, true);
192 GetSceneObjectAssetUuids(sog, assetUuids);
193 }
194 }
195
196 /// <summary>
197 /// Get all the asset uuids associated with a given object. This includes both those directly associated with
198 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
199 /// within this object).
200 /// </summary>
201 /// <param name="sceneObject"></param>
202 /// <param name="assetUuids"></param>
203 protected void GetSceneObjectAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, int> assetUuids)
204 {
205 m_log.DebugFormat(
206 "[ARCHIVER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
207
208 foreach (SceneObjectPart part in sceneObject.GetParts())
209 {
210 //m_log.DebugFormat(
211 // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);
212
213 try
214 {
215 Primitive.TextureEntry textureEntry = part.Shape.Textures;
216
217 // Get the prim's default texture. This will be used for faces which don't have their own texture
218 assetUuids[textureEntry.DefaultTexture.TextureID] = 1;
219
220 // XXX: Not a great way to iterate through face textures, but there's no
221 // other method available to tell how many faces there actually are
222 //int i = 0;
223 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
224 {
225 if (texture != null)
226 {
227 //m_log.DebugFormat("[ARCHIVER]: Got face {0}", i++);
228 assetUuids[texture.TextureID] = 1;
229 }
230 }
231
232 // If the prim is a sculpt then preserve this information too
233 if (part.Shape.SculptTexture != UUID.Zero)
234 assetUuids[part.Shape.SculptTexture] = 1;
235
236 // Now analyze this prim's inventory items to preserve all the uuids that they reference
237 foreach (TaskInventoryItem tii in part.TaskInventory.Values)
238 {
239 //m_log.DebugFormat("[ARCHIVER]: Analysing item asset type {0}", tii.Type);
240
241 if (!assetUuids.ContainsKey(tii.AssetID))
242 {
243 assetUuids[tii.AssetID] = 1;
244
245 if ((int)AssetType.Bodypart == tii.Type || ((int)AssetType.Clothing == tii.Type))
246 {
247 GetWearableAssetUuids(tii.AssetID, assetUuids);
248 }
249 else if ((int)AssetType.LSLText == tii.Type)
250 {
251 GetScriptAssetUuids(tii.AssetID, assetUuids);
252 }
253 else if ((int)AssetType.Object == tii.Type)
254 {
255 GetSceneObjectAssetUuids(tii.AssetID, assetUuids);
256 }
257 //else
258 //{
259 //m_log.DebugFormat("[ARCHIVER]: Recording asset {0} in object {1}", tii.AssetID, part.UUID);
260 //}
261 }
262 }
263 }
264 catch (Exception e)
265 {
266 m_log.ErrorFormat("[ARCHIVER]: Failed to get part - {0}", e);
267 m_log.DebugFormat("[ARCHIVER]: Texture entry length for prim was {0} (min is 46)", part.Shape.TextureEntry.Length);
268 }
269 }
270 }
271
272 /// <summary>
273 /// Archive the region requested.
274 /// </summary>
275 /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception>
276 public void ArchiveRegion()
277 {
278 Dictionary<UUID, int> assetUuids = new Dictionary<UUID, int>();
279
280 List<EntityBase> entities = m_scene.GetEntities();
281 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
282
283 // Filter entities so that we only have scene objects.
284 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
285 // end up having to do this
286 foreach (EntityBase entity in entities)
287 {
288 if (entity is SceneObjectGroup)
289 {
290 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
291
292 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
293 sceneObjects.Add((SceneObjectGroup)entity);
294 }
295 }
296
297 foreach (SceneObjectGroup sceneObject in sceneObjects)
298 {
299 GetSceneObjectAssetUuids(sceneObject, assetUuids);
300 }
301
302 m_log.DebugFormat(
303 "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
304 sceneObjects.Count, assetUuids.Count);
305
306 // Make sure that we also request terrain texture assets
307 RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings;
308
309 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
310 assetUuids[regionSettings.TerrainTexture1] = 1;
311
312 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
313 assetUuids[regionSettings.TerrainTexture2] = 1;
314
315 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
316 assetUuids[regionSettings.TerrainTexture3] = 1;
317
318 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
319 assetUuids[regionSettings.TerrainTexture4] = 1;
320
321 // Asynchronously request all the assets required to perform this archive operation
322 ArchiveWriteRequestExecution awre
323 = new ArchiveWriteRequestExecution(
324 sceneObjects,
325 m_scene.RequestModuleInterface<ITerrainModule>(),
326 m_scene.RequestModuleInterface<IRegionSerialiserModule>(),
327 m_scene,
328 m_saveStream);
329
330 new AssetsRequest(assetUuids.Keys, m_scene.AssetCache, awre.ReceivedAllAssets).Execute();
331 }
332 }
333}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiverModule.cs
deleted file mode 100644
index cd81169..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiverModule.cs
+++ /dev/null
@@ -1,95 +0,0 @@
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 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 */
27
28using System.Collections.Generic;
29using System.IO;
30using System.Reflection;
31using System.Threading;
32using OpenMetaverse;
33using log4net;
34using Nini.Config;
35using OpenSim.Framework.Communications.Cache;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Region.Environment.Modules.World.Serialiser;
39
40namespace OpenSim.Region.Environment.Modules.World.Archiver
41{
42 /// <summary>
43 /// This module loads and saves OpenSimulator archives
44 /// </summary>
45 public class ArchiverModule : IRegionModule, IRegionArchiverModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private Scene m_scene;
50
51 public string Name { get { return "Archiver Module"; } }
52
53 public bool IsSharedModule { get { return false; } }
54
55 public void Initialise(Scene scene, IConfigSource source)
56 {
57 m_scene = scene;
58 m_scene.RegisterModuleInterface<IRegionArchiverModule>(this);
59 }
60
61 public void PostInitialise()
62 {
63 }
64
65 public void Close()
66 {
67 }
68
69 public void ArchiveRegion(string savePath)
70 {
71 m_log.InfoFormat(
72 "[ARCHIVER]: Writing archive for region {0} to {1}", m_scene.RegionInfo.RegionName, savePath);
73
74 new ArchiveWriteRequestPreparation(m_scene, savePath).ArchiveRegion();
75 }
76
77 public void ArchiveRegion(Stream saveStream)
78 {
79 new ArchiveWriteRequestPreparation(m_scene, saveStream).ArchiveRegion();
80 }
81
82 public void DearchiveRegion(string loadPath)
83 {
84 m_log.InfoFormat(
85 "[ARCHIVER]: Loading archive to region {0} from {1}", m_scene.RegionInfo.RegionName, loadPath);
86
87 new ArchiveReadRequest(m_scene, loadPath).DearchiveRegion();
88 }
89
90 public void DearchiveRegion(Stream loadStream)
91 {
92 new ArchiveReadRequest(m_scene, loadStream).DearchiveRegion();
93 }
94 }
95}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsArchiver.cs b/OpenSim/Region/Environment/Modules/World/Archiver/AssetsArchiver.cs
deleted file mode 100644
index 36a60f3..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsArchiver.cs
+++ /dev/null
@@ -1,143 +0,0 @@
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 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 */
27
28using System.Collections.Generic;
29using System.IO;
30using System.Reflection;
31using System.Xml;
32using OpenMetaverse;
33using log4net;
34using OpenSim.Framework;
35
36namespace OpenSim.Region.Environment.Modules.World.Archiver
37{
38 /// <summary>
39 /// Archives assets
40 /// </summary>
41 public class AssetsArchiver
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 /// <summary>
46 /// Archive assets
47 /// </summary>
48 protected IDictionary<UUID, AssetBase> m_assets;
49
50 public AssetsArchiver(IDictionary<UUID, AssetBase> assets)
51 {
52 m_assets = assets;
53 }
54
55 /// <summary>
56 /// Archive the assets given to this archiver to the given archive.
57 /// </summary>
58 /// <param name="archive"></param>
59 public void Archive(TarArchiveWriter archive)
60 {
61 //WriteMetadata(archive);
62 WriteData(archive);
63 }
64
65 /// <summary>
66 /// Write an assets metadata file to the given archive
67 /// </summary>
68 /// <param name="archive"></param>
69 protected void WriteMetadata(TarArchiveWriter archive)
70 {
71 StringWriter sw = new StringWriter();
72 XmlTextWriter xtw = new XmlTextWriter(sw);
73
74 xtw.Formatting = Formatting.Indented;
75 xtw.WriteStartDocument();
76
77 xtw.WriteStartElement("assets");
78
79 foreach (UUID uuid in m_assets.Keys)
80 {
81 AssetBase asset = m_assets[uuid];
82
83 if (asset != null)
84 {
85 xtw.WriteStartElement("asset");
86
87 string extension = string.Empty;
88
89 if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(asset.Metadata.Type))
90 {
91 extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[asset.Metadata.Type];
92 }
93
94 xtw.WriteElementString("filename", uuid.ToString() + extension);
95
96 xtw.WriteElementString("name", asset.Metadata.Name);
97 xtw.WriteElementString("description", asset.Metadata.Description);
98 xtw.WriteElementString("asset-type", asset.Metadata.Type.ToString());
99
100 xtw.WriteEndElement();
101 }
102 }
103
104 xtw.WriteEndElement();
105
106 xtw.WriteEndDocument();
107
108 archive.AddFile("assets.xml", sw.ToString());
109 }
110
111 /// <summary>
112 /// Write asset data files to the given archive
113 /// </summary>
114 /// <param name="archive"></param>
115 protected void WriteData(TarArchiveWriter archive)
116 {
117 // It appears that gtar, at least, doesn't need the intermediate directory entries in the tar
118 //archive.AddDir("assets");
119
120 foreach (UUID uuid in m_assets.Keys)
121 {
122 AssetBase asset = m_assets[uuid];
123
124 string extension = string.Empty;
125
126 if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(asset.Metadata.Type))
127 {
128 extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[asset.Metadata.Type];
129 }
130 else
131 {
132 m_log.ErrorFormat(
133 "[ARCHIVER]: Unrecognized asset type {0} with uuid {1}. This asset will be saved but not reloaded",
134 asset.Metadata.Type, asset.Metadata.ID);
135 }
136
137 archive.AddFile(
138 ArchiveConstants.ASSETS_PATH + uuid.ToString() + extension,
139 asset.Data);
140 }
141 }
142 }
143}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsDearchiver.cs b/OpenSim/Region/Environment/Modules/World/Archiver/AssetsDearchiver.cs
deleted file mode 100644
index 95ff468..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsDearchiver.cs
+++ /dev/null
@@ -1,184 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Xml;
33using OpenMetaverse;
34using log4net;
35using OpenSim.Framework;
36using OpenSim.Framework.Communications.Cache;
37
38namespace OpenSim.Region.Environment.Modules.World.Archiver
39{
40 /// <summary>
41 /// Dearchives assets
42 /// </summary>
43 public class AssetsDearchiver
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 protected static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding();
48
49 /// <summary>
50 /// Store for asset data we received before we get the metadata
51 /// </summary>
52 protected Dictionary<string, byte[]> m_assetDataAwaitingMetadata = new Dictionary<string, byte[]>();
53
54 /// <summary>
55 /// Asset metadata. Is null if asset metadata isn't yet available.
56 /// </summary>
57 protected Dictionary<string, AssetMetadata> m_metadata;
58
59 /// <summary>
60 /// Cache to which dearchived assets will be added
61 /// </summary>
62 protected IAssetCache m_cache;
63
64 public AssetsDearchiver(IAssetCache cache)
65 {
66 m_cache = cache;
67 }
68
69 /// <summary>
70 /// Add asset data to the dearchiver
71 /// </summary>
72 /// <param name="assetFilename"></param>
73 /// <param name="data"></param>
74 public void AddAssetData(string assetFilename, byte[] data)
75 {
76 if (null == m_metadata)
77 {
78 m_assetDataAwaitingMetadata[assetFilename] = data;
79 }
80 else
81 {
82 ResolveAssetData(assetFilename, data);
83 }
84 }
85
86 /// <summary>
87 /// Add asset metadata xml
88 /// </summary>
89 /// <param name="xml"></param>
90 public void AddAssetMetadata(string xml)
91 {
92 m_metadata = new Dictionary<string, AssetMetadata>();
93
94 StringReader sr = new StringReader(xml);
95 XmlTextReader reader = new XmlTextReader(sr);
96
97 reader.ReadStartElement("assets");
98 reader.Read();
99
100 while (reader.Name.Equals("asset"))
101 {
102 reader.Read();
103
104 AssetMetadata metadata = new AssetMetadata();
105
106 string filename = reader.ReadElementString("filename");
107 m_log.DebugFormat("[DEARCHIVER]: Reading node {0}", filename);
108
109 metadata.Name = reader.ReadElementString("name");
110 metadata.Description = reader.ReadElementString("description");
111 metadata.AssetType = Convert.ToSByte(reader.ReadElementString("asset-type"));
112
113 m_metadata[filename] = metadata;
114
115 // Read asset end tag
116 reader.ReadEndElement();
117
118 reader.Read();
119 }
120
121 m_log.DebugFormat("[DEARCHIVER]: Resolved {0} items of asset metadata", m_metadata.Count);
122
123 ResolvePendingAssetData();
124 }
125
126 /// <summary>
127 /// Resolve asset data that we collected before receiving the metadata
128 /// </summary>
129 protected void ResolvePendingAssetData()
130 {
131 foreach (string filename in m_assetDataAwaitingMetadata.Keys)
132 {
133 ResolveAssetData(filename, m_assetDataAwaitingMetadata[filename]);
134 }
135 }
136
137 /// <summary>
138 /// Resolve a new piece of asset data against stored metadata
139 /// </summary>
140 /// <param name="assetFilename"></param>
141 /// <param name="data"></param>
142 protected void ResolveAssetData(string assetPath, byte[] data)
143 {
144 // Right now we're nastily obtaining the UUID from the filename
145 string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
146
147 if (m_metadata.ContainsKey(filename))
148 {
149 AssetMetadata metadata = m_metadata[filename];
150
151 if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(metadata.AssetType))
152 {
153 string extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[metadata.AssetType];
154 filename = filename.Remove(filename.Length - extension.Length);
155 }
156
157 m_log.DebugFormat("[ARCHIVER]: Importing asset {0}", filename);
158
159 AssetBase asset = new AssetBase(new UUID(filename), metadata.Name);
160 asset.Metadata.Description = metadata.Description;
161 asset.Metadata.Type = metadata.AssetType;
162 asset.Data = data;
163
164 m_cache.AddAsset(asset);
165 }
166 else
167 {
168 m_log.ErrorFormat(
169 "[DEARCHIVER]: Tried to dearchive data with filename {0} without any corresponding metadata",
170 assetPath);
171 }
172 }
173
174 /// <summary>
175 /// Metadata for an asset
176 /// </summary>
177 protected struct AssetMetadata
178 {
179 public string Name;
180 public string Description;
181 public sbyte AssetType;
182 }
183 }
184}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/Environment/Modules/World/Archiver/AssetsRequest.cs
deleted file mode 100644
index b7fd170..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsRequest.cs
+++ /dev/null
@@ -1,138 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using OpenMetaverse;
33using log4net;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications.Cache;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38
39namespace OpenSim.Region.Environment.Modules.World.Archiver
40{
41 /// <summary>
42 /// Encapsulate the asynchronous requests for the assets required for an archive operation
43 /// </summary>
44 class AssetsRequest
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 /// <summary>
49 /// uuids to request
50 /// </summary>
51 protected ICollection<UUID> m_uuids;
52
53 /// <summary>
54 /// Callback used when all the assets requested have been received.
55 /// </summary>
56 protected AssetsRequestCallback m_assetsRequestCallback;
57
58 /// <summary>
59 /// Assets retrieved in this request
60 /// </summary>
61 protected Dictionary<UUID, AssetBase> m_assets = new Dictionary<UUID, AssetBase>();
62
63 /// <summary>
64 /// Maintain a list of assets that could not be found. This will be passed back to the requester.
65 /// </summary>
66 protected List<UUID> m_notFoundAssetUuids = new List<UUID>();
67
68 /// <summary>
69 /// Record the number of asset replies required so we know when we've finished
70 /// </summary>
71 private int m_repliesRequired;
72
73 /// <summary>
74 /// Asset cache used to request the assets
75 /// </summary>
76 protected IAssetCache m_assetCache;
77
78 protected internal AssetsRequest(ICollection<UUID> uuids, IAssetCache assetCache, AssetsRequestCallback assetsRequestCallback)
79 {
80 m_uuids = uuids;
81 m_assetsRequestCallback = assetsRequestCallback;
82 m_assetCache = assetCache;
83 m_repliesRequired = uuids.Count;
84 }
85
86 protected internal void Execute()
87 {
88 // We can stop here if there are no assets to fetch
89 if (m_repliesRequired == 0)
90 m_assetsRequestCallback(m_assets, m_notFoundAssetUuids);
91
92 foreach (UUID uuid in m_uuids)
93 {
94 m_assetCache.GetAsset(uuid, AssetRequestCallback, true);
95 }
96 }
97
98 /// <summary>
99 /// Called back by the asset cache when it has the asset
100 /// </summary>
101 /// <param name="assetID"></param>
102 /// <param name="asset"></param>
103 public void AssetRequestCallback(UUID assetID, AssetBase asset)
104 {
105 if (asset != null)
106 m_assets[assetID] = asset;
107 else
108 m_notFoundAssetUuids.Add(assetID);
109
110 //m_log.DebugFormat(
111 // "[ARCHIVER]: Received {0} assets and notification of {1} missing assets", m_assets.Count, m_notFoundAssetUuids.Count);
112
113 if (m_assets.Count + m_notFoundAssetUuids.Count == m_repliesRequired)
114 {
115 // We want to stop using the asset cache thread asap as we now need to do the actual work of producing the archive
116 Thread newThread = new Thread(PerformAssetsRequestCallback);
117 newThread.Name = "OpenSimulator archiving thread post assets receipt";
118 newThread.Start();
119 }
120 }
121
122 /// <summary>
123 /// Perform the callback on the original requester of the assets
124 /// </summary>
125 protected void PerformAssetsRequestCallback()
126 {
127 try
128 {
129 m_assetsRequestCallback(m_assets, m_notFoundAssetUuids);
130 }
131 catch (Exception e)
132 {
133 m_log.ErrorFormat(
134 "[ARCHIVER]: Terminating archive creation since asset requster callback failed with {0}", e);
135 }
136 }
137 }
138}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs b/OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs
deleted file mode 100644
index e12d0ec..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs
+++ /dev/null
@@ -1,258 +0,0 @@
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 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 */
27
28using System;
29using System.IO;
30using System.Text;
31using System.Xml;
32using OpenMetaverse;
33using OpenSim.Framework;
34
35namespace OpenSim.Region.Environment.Modules.World.Archiver
36{
37 /// <summary>
38 /// Serialize and deserialize region settings for an archive file format.
39 /// </summary>
40 /// We didn't simply use automatic .NET serializagion for OpenSim.Framework.RegionSettings since this is really
41 /// a file format rather than an object serialization.
42 /// TODO: However, we could still have used separate non-framework classes here to read and write the xml
43 /// automatically rather than laboriously doing it by hand using XmlTextReader and Writer. Should switch to this
44 /// in the future.
45 public class RegionSettingsSerializer
46 {
47 protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
48
49 /// <summary>
50 /// Deserialize region settings
51 /// </summary>
52 /// <param name="serializedSettings"></param>
53 /// <returns></returns>
54 /// <exception cref="System.Xml.XmlException"></exception>
55 public static RegionSettings Deserialize(byte[] serializedSettings)
56 {
57 return Deserialize(m_asciiEncoding.GetString(serializedSettings, 0, serializedSettings.Length));
58 }
59
60 /// <summary>
61 /// Deserialize region settings
62 /// </summary>
63 /// <param name="serializedSettings"></param>
64 /// <returns></returns>
65 /// <exception cref="System.Xml.XmlException"></exception>
66 public static RegionSettings Deserialize(string serializedSettings)
67 {
68 RegionSettings settings = new RegionSettings();
69
70 StringReader sr = new StringReader(serializedSettings);
71 XmlTextReader xtr = new XmlTextReader(sr);
72
73 xtr.ReadStartElement("RegionSettings");
74
75 xtr.ReadStartElement("General");
76
77 while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement)
78 {
79 switch (xtr.Name)
80 {
81 case "AllowDamage":
82 settings.AllowDamage = bool.Parse(xtr.ReadElementContentAsString());
83 break;
84 case "AllowLandResell":
85 settings.AllowLandResell = bool.Parse(xtr.ReadElementContentAsString());
86 break;
87 case "AllowLandJoinDivide":
88 settings.AllowLandJoinDivide = bool.Parse(xtr.ReadElementContentAsString());
89 break;
90 case "BlockFly":
91 settings.BlockFly = bool.Parse(xtr.ReadElementContentAsString());
92 break;
93 case "BlockLandShowInSearch":
94 settings.BlockShowInSearch = bool.Parse(xtr.ReadElementContentAsString());
95 break;
96 case "BlockTerraform":
97 settings.BlockTerraform = bool.Parse(xtr.ReadElementContentAsString());
98 break;
99 case "DisableCollisions":
100 settings.DisableCollisions = bool.Parse(xtr.ReadElementContentAsString());
101 break;
102 case "DisablePhysics":
103 settings.DisablePhysics = bool.Parse(xtr.ReadElementContentAsString());
104 break;
105 case "DisableScripts":
106 settings.DisableScripts = bool.Parse(xtr.ReadElementContentAsString());
107 break;
108 case "MaturityRating":
109 settings.Maturity = int.Parse(xtr.ReadElementContentAsString());
110 break;
111 case "RestrictPushing":
112 settings.RestrictPushing = bool.Parse(xtr.ReadElementContentAsString());
113 break;
114 case "AgentLimit":
115 settings.AgentLimit = int.Parse(xtr.ReadElementContentAsString());
116 break;
117 case "ObjectBonus":
118 settings.ObjectBonus = double.Parse(xtr.ReadElementContentAsString());
119 break;
120 }
121 }
122
123 xtr.ReadEndElement();
124 xtr.ReadStartElement("GroundTextures");
125
126 while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement)
127 {
128 switch (xtr.Name)
129 {
130 case "Texture1":
131 settings.TerrainTexture1 = UUID.Parse(xtr.ReadElementContentAsString());
132 break;
133 case "Texture2":
134 settings.TerrainTexture2 = UUID.Parse(xtr.ReadElementContentAsString());
135 break;
136 case "Texture3":
137 settings.TerrainTexture3 = UUID.Parse(xtr.ReadElementContentAsString());
138 break;
139 case "Texture4":
140 settings.TerrainTexture4 = UUID.Parse(xtr.ReadElementContentAsString());
141 break;
142 case "ElevationLowSW":
143 settings.Elevation1SW = double.Parse(xtr.ReadElementContentAsString());
144 break;
145 case "ElevationLowNW":
146 settings.Elevation1NW = double.Parse(xtr.ReadElementContentAsString());
147 break;
148 case "ElevationLowSE":
149 settings.Elevation1SE = double.Parse(xtr.ReadElementContentAsString());
150 break;
151 case "ElevationLowNE":
152 settings.Elevation1NE = double.Parse(xtr.ReadElementContentAsString());
153 break;
154 case "ElevationHighSW":
155 settings.Elevation1SW = double.Parse(xtr.ReadElementContentAsString());
156 break;
157 case "ElevationHighNW":
158 settings.Elevation2NW = double.Parse(xtr.ReadElementContentAsString());
159 break;
160 case "ElevationHighSE":
161 settings.Elevation2SE = double.Parse(xtr.ReadElementContentAsString());
162 break;
163 case "ElevationHighNE":
164 settings.Elevation2NE = double.Parse(xtr.ReadElementContentAsString());
165 break;
166 }
167 }
168
169 xtr.ReadEndElement();
170 xtr.ReadStartElement("Terrain");
171
172 while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement)
173 {
174 switch (xtr.Name)
175 {
176 case "WaterHeight":
177 settings.WaterHeight = double.Parse(xtr.ReadElementContentAsString());
178 break;
179 case "TerrainRaiseLimit":
180 settings.TerrainRaiseLimit = double.Parse(xtr.ReadElementContentAsString());
181 break;
182 case "TerrainLowerLimit":
183 settings.TerrainLowerLimit = double.Parse(xtr.ReadElementContentAsString());
184 break;
185 case "UseEstateSun":
186 settings.UseEstateSun = bool.Parse(xtr.ReadElementContentAsString());
187 break;
188 case "FixedSun":
189 settings.FixedSun = bool.Parse(xtr.ReadElementContentAsString());
190 break;
191 }
192 }
193
194 xtr.Close();
195 sr.Close();
196
197 return settings;
198 }
199
200 public static string Serialize(RegionSettings settings)
201 {
202 StringWriter sw = new StringWriter();
203 XmlTextWriter xtw = new XmlTextWriter(sw);
204 xtw.Formatting = Formatting.Indented;
205 xtw.WriteStartDocument();
206
207 xtw.WriteStartElement("RegionSettings");
208
209 xtw.WriteStartElement("General");
210 xtw.WriteElementString("AllowDamage", settings.AllowDamage.ToString());
211 xtw.WriteElementString("AllowLandResell", settings.AllowLandResell.ToString());
212 xtw.WriteElementString("AllowLandJoinDivide", settings.AllowLandJoinDivide.ToString());
213 xtw.WriteElementString("BlockFly", settings.BlockFly.ToString());
214 xtw.WriteElementString("BlockLandShowInSearch", settings.BlockShowInSearch.ToString());
215 xtw.WriteElementString("BlockTerraform", settings.BlockTerraform.ToString());
216 xtw.WriteElementString("DisableCollisions", settings.DisableCollisions.ToString());
217 xtw.WriteElementString("DisablePhysics", settings.DisablePhysics.ToString());
218 xtw.WriteElementString("DisableScripts", settings.DisableScripts.ToString());
219 xtw.WriteElementString("MaturityRating", settings.Maturity.ToString());
220 xtw.WriteElementString("RestrictPushing", settings.RestrictPushing.ToString());
221 xtw.WriteElementString("AgentLimit", settings.AgentLimit.ToString());
222 xtw.WriteElementString("ObjectBonus", settings.ObjectBonus.ToString());
223 xtw.WriteEndElement();
224
225 xtw.WriteStartElement("GroundTextures");
226 xtw.WriteElementString("Texture1", settings.TerrainTexture1.ToString());
227 xtw.WriteElementString("Texture2", settings.TerrainTexture2.ToString());
228 xtw.WriteElementString("Texture3", settings.TerrainTexture3.ToString());
229 xtw.WriteElementString("Texture4", settings.TerrainTexture4.ToString());
230 xtw.WriteElementString("ElevationLowSW", settings.Elevation1SW.ToString());
231 xtw.WriteElementString("ElevationLowNW", settings.Elevation1NW.ToString());
232 xtw.WriteElementString("ElevationLowSE", settings.Elevation1SE.ToString());
233 xtw.WriteElementString("ElevationLowNE", settings.Elevation1NE.ToString());
234 xtw.WriteElementString("ElevationHighSW", settings.Elevation2SW.ToString());
235 xtw.WriteElementString("ElevationHighNW", settings.Elevation2NW.ToString());
236 xtw.WriteElementString("ElevationHighSE", settings.Elevation2SE.ToString());
237 xtw.WriteElementString("ElevationHighNE", settings.Elevation2NE.ToString());
238 xtw.WriteEndElement();
239
240 xtw.WriteStartElement("Terrain");
241 xtw.WriteElementString("WaterHeight", settings.WaterHeight.ToString());
242 xtw.WriteElementString("TerrainRaiseLimit", settings.TerrainRaiseLimit.ToString());
243 xtw.WriteElementString("TerrainLowerLimit", settings.TerrainLowerLimit.ToString());
244 xtw.WriteElementString("UseEstateSun", settings.UseEstateSun.ToString());
245 xtw.WriteElementString("FixedSun", settings.FixedSun.ToString());
246 // XXX: Need to expose interface to get sun phase information from sun module
247 // xtw.WriteStartElement("SunPhase",
248 xtw.WriteEndElement();
249
250 xtw.WriteEndElement();
251
252 xtw.Close();
253 sw.Close();
254
255 return sw.ToString();
256 }
257 }
258}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveReader.cs b/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveReader.cs
deleted file mode 100644
index 3862546..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveReader.cs
+++ /dev/null
@@ -1,195 +0,0 @@
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 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 */
27
28using System;
29using System.IO;
30using System.Reflection;
31using System.Text;
32using log4net;
33
34namespace OpenSim.Region.Environment.Modules.World.Archiver
35{
36 /// <summary>
37 /// Temporary code to do the bare minimum required to read a tar archive for our purposes
38 /// </summary>
39 public class TarArchiveReader
40 {
41 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 public enum TarEntryType
44 {
45 TYPE_UNKNOWN = 0,
46 TYPE_NORMAL_FILE = 1,
47 TYPE_HARD_LINK = 2,
48 TYPE_SYMBOLIC_LINK = 3,
49 TYPE_CHAR_SPECIAL = 4,
50 TYPE_BLOCK_SPECIAL = 5,
51 TYPE_DIRECTORY = 6,
52 TYPE_FIFO = 7,
53 TYPE_CONTIGUOUS_FILE = 8,
54 }
55
56 protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
57
58 /// <summary>
59 /// Binary reader for the underlying stream
60 /// </summary>
61 protected BinaryReader m_br;
62
63 /// <summary>
64 /// Used to trim off null chars
65 /// </summary>
66 protected char[] m_nullCharArray = new char[] { '\0' };
67
68 /// <summary>
69 /// Generate a tar reader which reads from the given stream.
70 /// </summary>
71 /// <param name="s"></param>
72 public TarArchiveReader(Stream s)
73 {
74 m_br = new BinaryReader(s);
75 }
76
77 /// <summary>
78 /// Read the next entry in the tar file.
79 /// </summary>
80 /// <param name="filePath"></param>
81 /// <returns>the data for the entry. Returns null if there are no more entries</returns>
82 public byte[] ReadEntry(out string filePath, out TarEntryType entryType)
83 {
84 filePath = String.Empty;
85 entryType = TarEntryType.TYPE_UNKNOWN;
86 TarHeader header = ReadHeader();
87
88 if (null == header)
89 return null;
90
91 entryType = header.EntryType;
92 filePath = header.FilePath;
93 byte[] data = m_br.ReadBytes(header.FileSize);
94
95 //m_log.DebugFormat("[TAR ARCHIVE READER]: filePath {0}, fileSize {1}", filePath, header.FileSize);
96
97 // Read the rest of the empty padding in the 512 byte block
98 if (header.FileSize % 512 != 0)
99 {
100 int paddingLeft = 512 - (header.FileSize % 512);
101
102 //m_log.DebugFormat("[TAR ARCHIVE READER]: Reading {0} padding bytes", paddingLeft);
103
104 m_br.ReadBytes(paddingLeft);
105 }
106
107 return data;
108 }
109
110 /// <summary>
111 /// Read the next 512 byte chunk of data as a tar header.
112 /// </summary>
113 /// <returns>A tar header struct. null if we have reached the end of the archive.</returns>
114 protected TarHeader ReadHeader()
115 {
116 byte[] header = m_br.ReadBytes(512);
117
118 // If we've reached the end of the archive we'll be in null block territory, which means
119 // the next byte will be 0
120 if (header[0] == 0)
121 return null;
122
123 TarHeader tarHeader = new TarHeader();
124
125 tarHeader.FilePath = m_asciiEncoding.GetString(header, 0, 100);
126 tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray);
127 tarHeader.FileSize = ConvertOctalBytesToDecimal(header, 124, 11);
128
129 switch (header[156])
130 {
131 case 0:
132 tarHeader.EntryType = TarEntryType.TYPE_NORMAL_FILE;
133 break;
134 case (byte)'0':
135 tarHeader.EntryType = TarEntryType.TYPE_NORMAL_FILE;
136 break;
137 case (byte)'1':
138 tarHeader.EntryType = TarEntryType.TYPE_HARD_LINK;
139 break;
140 case (byte)'2':
141 tarHeader.EntryType = TarEntryType.TYPE_SYMBOLIC_LINK;
142 break;
143 case (byte)'3':
144 tarHeader.EntryType = TarEntryType.TYPE_CHAR_SPECIAL;
145 break;
146 case (byte)'4':
147 tarHeader.EntryType = TarEntryType.TYPE_BLOCK_SPECIAL;
148 break;
149 case (byte)'5':
150 tarHeader.EntryType = TarEntryType.TYPE_DIRECTORY;
151 break;
152 case (byte)'6':
153 tarHeader.EntryType = TarEntryType.TYPE_FIFO;
154 break;
155 case (byte)'7':
156 tarHeader.EntryType = TarEntryType.TYPE_CONTIGUOUS_FILE;
157 break;
158 }
159
160 return tarHeader;
161 }
162
163 public void Close()
164 {
165 m_br.Close();
166 }
167
168 /// <summary>
169 /// Convert octal bytes to a decimal representation
170 /// </summary>
171 /// <param name="bytes"></param>
172 /// <returns></returns>
173 public static int ConvertOctalBytesToDecimal(byte[] bytes, int startIndex, int count)
174 {
175 string oString = m_asciiEncoding.GetString(bytes, startIndex, count);
176
177 int d = 0;
178
179 foreach (char c in oString)
180 {
181 d <<= 3;
182 d |= c - '0';
183 }
184
185 return d;
186 }
187 }
188
189 public class TarHeader
190 {
191 public string FilePath;
192 public int FileSize;
193 public TarArchiveReader.TarEntryType EntryType;
194 }
195}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs b/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs
deleted file mode 100644
index 8fd247c..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs
+++ /dev/null
@@ -1,202 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Text;
32using System.Reflection;
33using log4net;
34
35namespace OpenSim.Region.Environment.Modules.World.Archiver
36{
37 /// <summary>
38 /// Temporary code to produce a tar archive in tar v7 format
39 /// </summary>
40 public class TarArchiveWriter
41 {
42 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 protected Dictionary<string, byte[]> m_files = new Dictionary<string, byte[]>();
45
46 protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
47
48 /// <summary>
49 /// Add a directory to the tar archive. We can only handle one path level right now!
50 /// </summary>
51 /// <param name="dirName"></param>
52 public void AddDir(string dirName)
53 {
54 // Directories are signalled by a final /
55 if (!dirName.EndsWith("/"))
56 dirName += "/";
57
58 AddFile(dirName, new byte[0]);
59 }
60
61 /// <summary>
62 /// Add a file to the tar archive
63 /// </summary>
64 /// <param name="filePath"></param>
65 /// <param name="data"></param>
66 public void AddFile(string filePath, string data)
67 {
68 AddFile(filePath, m_asciiEncoding.GetBytes(data));
69 }
70
71 /// <summary>
72 /// Add a file to the tar archive
73 /// </summary>
74 /// <param name="filePath"></param>
75 /// <param name="data"></param>
76 public void AddFile(string filePath, byte[] data)
77 {
78 m_files[filePath] = data;
79 }
80
81 /// <summary>
82 /// Write the raw tar archive data to a stream. The stream will be closed on completion.
83 /// </summary>
84 /// <param name="s">Stream to which to write the data</param>
85 /// <returns></returns>
86 public void WriteTar(Stream s)
87 {
88 BinaryWriter bw = new BinaryWriter(s);
89
90 foreach (string filePath in m_files.Keys)
91 {
92 byte[] header = new byte[512];
93 byte[] data = m_files[filePath];
94
95 // file path field (100)
96 byte[] nameBytes = m_asciiEncoding.GetBytes(filePath);
97 int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length;
98 Array.Copy(nameBytes, header, nameSize);
99
100 // file mode (8)
101 byte[] modeBytes = m_asciiEncoding.GetBytes("0000777");
102 Array.Copy(modeBytes, 0, header, 100, 7);
103
104 // owner user id (8)
105 byte[] ownerIdBytes = m_asciiEncoding.GetBytes("0000764");
106 Array.Copy(ownerIdBytes, 0, header, 108, 7);
107
108 // group user id (8)
109 byte[] groupIdBytes = m_asciiEncoding.GetBytes("0000764");
110 Array.Copy(groupIdBytes, 0, header, 116, 7);
111
112 // file size in bytes (12)
113 int fileSize = data.Length;
114 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: File size of {0} is {1}", filePath, fileSize);
115
116 byte[] fileSizeBytes = ConvertDecimalToPaddedOctalBytes(fileSize, 11);
117
118 Array.Copy(fileSizeBytes, 0, header, 124, 11);
119
120 // last modification time (12)
121 byte[] lastModTimeBytes = m_asciiEncoding.GetBytes("11017037332");
122 Array.Copy(lastModTimeBytes, 0, header, 136, 11);
123
124 // link indicator (1)
125 //header[156] = m_asciiEncoding.GetBytes("0")[0];
126 if (filePath.EndsWith("/"))
127 {
128 header[156] = m_asciiEncoding.GetBytes("5")[0];
129 }
130 else
131 {
132 header[156] = 0;
133 }
134
135 Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 329, 7);
136 Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 337, 7);
137
138 // check sum for header block (8) [calculated last]
139 Array.Copy(m_asciiEncoding.GetBytes(" "), 0, header, 148, 8);
140
141 int checksum = 0;
142 foreach (byte b in header)
143 {
144 checksum += b;
145 }
146
147 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Decimal header checksum is {0}", checksum);
148
149 byte[] checkSumBytes = ConvertDecimalToPaddedOctalBytes(checksum, 6);
150
151 Array.Copy(checkSumBytes, 0, header, 148, 6);
152
153 header[154] = 0;
154
155 // Write out header
156 bw.Write(header);
157
158 // Write out data
159 bw.Write(data);
160
161 if (data.Length % 512 != 0)
162 {
163 int paddingRequired = 512 - (data.Length % 512);
164
165 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Padding data with {0} bytes", paddingRequired);
166
167 byte[] padding = new byte[paddingRequired];
168 bw.Write(padding);
169 }
170 }
171
172 //m_log.Debug("[TAR ARCHIVE WRITER]: Writing final consecutive 0 blocks");
173
174 // Write two consecutive 0 blocks to end the archive
175 byte[] finalZeroPadding = new byte[1024];
176 bw.Write(finalZeroPadding);
177
178 bw.Flush();
179 bw.Close();
180 }
181
182 public static byte[] ConvertDecimalToPaddedOctalBytes(int d, int padding)
183 {
184 string oString = "";
185
186 while (d > 0)
187 {
188 oString = Convert.ToString((byte)'0' + d & 7) + oString;
189 d >>= 3;
190 }
191
192 while (oString.Length < padding)
193 {
194 oString = "0" + oString;
195 }
196
197 byte[] oBytes = m_asciiEncoding.GetBytes(oString);
198
199 return oBytes;
200 }
201 }
202}
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/Environment/Modules/World/Archiver/Tests/ArchiverTests.cs
deleted file mode 100644
index e265252..0000000
--- a/OpenSim/Region/Environment/Modules/World/Archiver/Tests/ArchiverTests.cs
+++ /dev/null
@@ -1,188 +0,0 @@
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 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 */
27
28using System;
29using System.IO;
30using System.Threading;
31using NUnit.Framework;
32using NUnit.Framework.SyntaxHelpers;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Environment.Modules.World.Archiver;
37using OpenSim.Region.Environment.Modules.World.Serialiser;
38using OpenSim.Region.Environment.Modules.World.Terrain;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Tests.Common.Setup;
41
42namespace OpenSim.Region.Environment.Modules.World.Archiver.Tests
43{
44 [TestFixture]
45 public class ArchiverTests
46 {
47 private EventWaitHandle m_waitHandle = new AutoResetEvent(false);
48
49 private void SaveCompleted(string errorMessage)
50 {
51 m_waitHandle.Set();
52 }
53
54 /// <summary>
55 /// Test saving a V0.2 OpenSim Region Archive.
56 /// </summary>
57 [Test]
58 public void TestSaveOarV0p2()
59 {
60 log4net.Config.XmlConfigurator.Configure();
61
62 ArchiverModule archiverModule = new ArchiverModule();
63 SerialiserModule serialiserModule = new SerialiserModule();
64 TerrainModule terrainModule = new TerrainModule();
65
66 Scene scene = SceneSetupHelpers.SetupScene();
67 SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
68
69 SceneObjectPart part1;
70
71 // Create and add prim 1
72 {
73 string partName = "My Little Pony";
74 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000015");
75 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
76 Vector3 groupPosition = new Vector3(10, 20, 30);
77 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
78 Vector3 offsetPosition = new Vector3(5, 10, 15);
79
80 part1
81 = new SceneObjectPart(
82 ownerId, shape, groupPosition, rotationOffset, offsetPosition);
83 part1.Name = partName;
84
85 scene.AddNewSceneObject(new SceneObjectGroup(part1), false);
86 }
87
88 SceneObjectPart part2;
89
90 // Create and add prim 2
91 {
92 string partName = "Action Man";
93 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000016");
94 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder();
95 Vector3 groupPosition = new Vector3(90, 80, 70);
96 Quaternion rotationOffset = new Quaternion(60, 70, 80, 90);
97 Vector3 offsetPosition = new Vector3(20, 25, 30);
98
99 part2
100 = new SceneObjectPart(
101 ownerId, shape, groupPosition, rotationOffset, offsetPosition);
102 part2.Name = partName;
103
104 scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
105 }
106
107 MemoryStream archiveWriteStream = new MemoryStream();
108
109 scene.EventManager.OnOarFileSaved += SaveCompleted;
110 archiverModule.ArchiveRegion(archiveWriteStream);
111 m_waitHandle.WaitOne(60000, true);
112
113 byte[] archive = archiveWriteStream.ToArray();
114 MemoryStream archiveReadStream = new MemoryStream(archive);
115 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
116
117 bool gotControlFile = false;
118 bool gotObject1File = false;
119 bool gotObject2File = false;
120 string expectedObject1FileName = string.Format(
121 "{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
122 part1.Name,
123 Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
124 part1.UUID);
125 string expectedObject2FileName = string.Format(
126 "{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
127 part2.Name,
128 Math.Round(part2.GroupPosition.X), Math.Round(part2.GroupPosition.Y), Math.Round(part2.GroupPosition.Z),
129 part2.UUID);
130
131 string filePath;
132 TarArchiveReader.TarEntryType tarEntryType;
133
134 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
135 {
136 if (ArchiveConstants.CONTROL_FILE_PATH == filePath)
137 {
138 gotControlFile = true;
139 }
140 else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
141 {
142 string fileName = filePath.Remove(0, ArchiveConstants.OBJECTS_PATH.Length);
143
144 if (fileName.StartsWith(part1.Name))
145 {
146 Assert.That(fileName, Is.EqualTo(expectedObject1FileName));
147 gotObject1File = true;
148 }
149 else if (fileName.StartsWith(part2.Name))
150 {
151 Assert.That(fileName, Is.EqualTo(expectedObject2FileName));
152 gotObject2File = true;
153 }
154 }
155 }
156
157 Assert.That(gotControlFile, Is.True, "No control file in archive");
158 Assert.That(gotObject1File, Is.True, "No object1 file in archive");
159 Assert.That(gotObject2File, Is.True, "No object2 file in archive");
160
161 // TODO: Test presence of more files and contents of files.
162 }
163
164 /// <summary>
165 /// Test loading a V0.2 OpenSim Region Archive. Does not yet do what it says on the tin.
166 /// </summary>
167 [Test]
168 public void TestLoadOarV0p2()
169 {
170 MemoryStream archiveWriteStream = new MemoryStream();
171 TarArchiveWriter tar = new TarArchiveWriter();
172
173 tar.AddFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestExecution.Create0p2ControlFile());
174 tar.WriteTar(archiveWriteStream);
175
176 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
177
178 ArchiverModule archiverModule = new ArchiverModule();
179
180 Scene scene = SceneSetupHelpers.SetupScene();
181 SceneSetupHelpers.SetupSceneModules(scene, archiverModule);
182
183 archiverModule.DearchiveRegion(archiveReadStream);
184
185 // TODO: Okay, so nothing is tested yet apart from the fact that it doesn't blow up
186 }
187 }
188} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs
deleted file mode 100644
index 6b74c83..0000000
--- a/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs
+++ /dev/null
@@ -1,1012 +0,0 @@
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 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 System;
28using System.Threading;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenMetaverse;
32using log4net;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38namespace OpenSim.Region.Environment.Modules.World.Estate
39{
40 public class EstateManagementModule : IEstateModule
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 private delegate void LookupUUIDS(List<UUID> uuidLst);
45
46 private Scene m_scene;
47
48 private EstateTerrainXferHandler TerrainUploader = null;
49
50 #region Packet Data Responders
51
52 private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice)
53 {
54 uint sun = 0;
55
56 if (!m_scene.RegionInfo.EstateSettings.UseGlobalTime)
57 sun=(uint)(m_scene.RegionInfo.EstateSettings.SunPosition*1024.0) + 0x1800;
58 UUID estateOwner;
59 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
60 estateOwner = m_scene.RegionInfo.EstateSettings.EstateOwner;
61 else
62 estateOwner = m_scene.RegionInfo.MasterAvatarAssignedUUID;
63
64 if (m_scene.Permissions.IsGod(remote_client.AgentId))
65 estateOwner = remote_client.AgentId;
66
67 remote_client.SendDetailedEstateData(invoice,
68 m_scene.RegionInfo.EstateSettings.EstateName,
69 m_scene.RegionInfo.EstateSettings.EstateID,
70 m_scene.RegionInfo.EstateSettings.ParentEstateID,
71 GetEstateFlags(),
72 sun,
73 m_scene.RegionInfo.RegionSettings.Covenant,
74 m_scene.RegionInfo.EstateSettings.AbuseEmail,
75 estateOwner);
76
77 remote_client.SendEstateManagersList(invoice,
78 m_scene.RegionInfo.EstateSettings.EstateManagers,
79 m_scene.RegionInfo.EstateSettings.EstateID);
80
81 remote_client.SendBannedUserList(invoice,
82 m_scene.RegionInfo.EstateSettings.EstateBans,
83 m_scene.RegionInfo.EstateSettings.EstateID);
84 }
85
86 private void estateSetRegionInfoHandler(bool blockTerraform, bool noFly, bool allowDamage, bool blockLandResell, int maxAgents, float objectBonusFactor,
87 int matureLevel, bool restrictPushObject, bool allowParcelChanges)
88 {
89 if (blockTerraform)
90 m_scene.RegionInfo.RegionSettings.BlockTerraform = true;
91 else
92 m_scene.RegionInfo.RegionSettings.BlockTerraform = false;
93
94 if (noFly)
95 m_scene.RegionInfo.RegionSettings.BlockFly = true;
96 else
97 m_scene.RegionInfo.RegionSettings.BlockFly = false;
98
99 if (allowDamage)
100 m_scene.RegionInfo.RegionSettings.AllowDamage = true;
101 else
102 m_scene.RegionInfo.RegionSettings.AllowDamage = false;
103
104 if (blockLandResell)
105 m_scene.RegionInfo.RegionSettings.AllowLandResell = false;
106 else
107 m_scene.RegionInfo.RegionSettings.AllowLandResell = true;
108
109 m_scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents;
110
111 m_scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor;
112
113 if (matureLevel <= 13)
114 m_scene.RegionInfo.RegionSettings.Maturity = 0;
115 else
116 m_scene.RegionInfo.RegionSettings.Maturity = 1;
117
118 if (restrictPushObject)
119 m_scene.RegionInfo.RegionSettings.RestrictPushing = true;
120 else
121 m_scene.RegionInfo.RegionSettings.RestrictPushing = false;
122
123 if (allowParcelChanges)
124 m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide = true;
125 else
126 m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide = false;
127
128 m_scene.RegionInfo.RegionSettings.Save();
129
130 sendRegionInfoPacketToAll();
131 }
132
133 public void setEstateTerrainBaseTexture(IClientAPI remoteClient, int corner, UUID texture)
134 {
135 if (texture == UUID.Zero)
136 return;
137
138 switch (corner)
139 {
140 case 0:
141 m_scene.RegionInfo.RegionSettings.TerrainTexture1 = texture;
142 break;
143 case 1:
144 m_scene.RegionInfo.RegionSettings.TerrainTexture2 = texture;
145 break;
146 case 2:
147 m_scene.RegionInfo.RegionSettings.TerrainTexture3 = texture;
148 break;
149 case 3:
150 m_scene.RegionInfo.RegionSettings.TerrainTexture4 = texture;
151 break;
152 }
153 m_scene.RegionInfo.RegionSettings.Save();
154 }
155
156 public void setEstateTerrainTextureHeights(IClientAPI client, int corner, float lowValue, float highValue)
157 {
158 switch (corner)
159 {
160 case 0:
161 m_scene.RegionInfo.RegionSettings.Elevation1SW = lowValue;
162 m_scene.RegionInfo.RegionSettings.Elevation2SW = highValue;
163 break;
164 case 1:
165 m_scene.RegionInfo.RegionSettings.Elevation1NW = lowValue;
166 m_scene.RegionInfo.RegionSettings.Elevation2NW = highValue;
167 break;
168 case 2:
169 m_scene.RegionInfo.RegionSettings.Elevation1SE = lowValue;
170 m_scene.RegionInfo.RegionSettings.Elevation2SE = highValue;
171 break;
172 case 3:
173 m_scene.RegionInfo.RegionSettings.Elevation1NE = lowValue;
174 m_scene.RegionInfo.RegionSettings.Elevation2NE = highValue;
175 break;
176 }
177 m_scene.RegionInfo.RegionSettings.Save();
178 }
179
180 private void handleCommitEstateTerrainTextureRequest(IClientAPI remoteClient)
181 {
182 sendRegionHandshakeToAll();
183 }
184
185 public void setRegionTerrainSettings(float WaterHeight,
186 float TerrainRaiseLimit, float TerrainLowerLimit,
187 bool UseEstateSun, bool UseFixedSun, float SunHour,
188 bool UseGlobal, bool EstateFixedSun, float EstateSunHour)
189 {
190 // Water Height
191 m_scene.RegionInfo.RegionSettings.WaterHeight = WaterHeight;
192
193 // Terraforming limits
194 m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit = TerrainRaiseLimit;
195 m_scene.RegionInfo.RegionSettings.TerrainLowerLimit = TerrainLowerLimit;
196
197 // Time of day / fixed sun
198 m_scene.RegionInfo.RegionSettings.UseEstateSun = UseEstateSun;
199 m_scene.RegionInfo.RegionSettings.FixedSun = UseFixedSun;
200 m_scene.RegionInfo.RegionSettings.SunPosition = SunHour;
201
202 m_scene.EventManager.TriggerEstateToolsTimeUpdate(m_scene.RegionInfo.RegionHandle, UseFixedSun, UseEstateSun, SunHour);
203
204 //m_log.Debug("[ESTATE]: UFS: " + UseFixedSun.ToString());
205 //m_log.Debug("[ESTATE]: SunHour: " + SunHour.ToString());
206
207 sendRegionInfoPacketToAll();
208 m_scene.RegionInfo.RegionSettings.Save();
209 }
210
211 private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds)
212 {
213 m_scene.Restart(timeInSeconds);
214 }
215
216 private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID)
217 {
218 m_scene.RegionInfo.RegionSettings.Covenant = estateCovenantID;
219 m_scene.RegionInfo.RegionSettings.Save();
220 }
221
222 private void handleEstateAccessDeltaRequest(IClientAPI remote_client, UUID invoice, int estateAccessType, UUID user)
223 {
224 // EstateAccessDelta handles Estate Managers, Sim Access, Sim Banlist, allowed Groups.. etc.
225
226 if (user == m_scene.RegionInfo.EstateSettings.EstateOwner)
227 return; // never process EO
228 if (user == m_scene.RegionInfo.MasterAvatarAssignedUUID)
229 return; // never process owner
230
231 switch (estateAccessType)
232 {
233 case 64:
234 if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || m_scene.Permissions.BypassPermissions())
235 {
236 EstateBan[] banlistcheck = m_scene.RegionInfo.EstateSettings.EstateBans;
237
238 bool alreadyInList = false;
239
240 for (int i = 0; i < banlistcheck.Length; i++)
241 {
242 if (user == banlistcheck[i].bannedUUID)
243 {
244 alreadyInList = true;
245 break;
246 }
247
248 }
249 if (!alreadyInList)
250 {
251
252 EstateBan item = new EstateBan();
253
254 item.bannedUUID = user;
255 item.estateID = m_scene.RegionInfo.EstateSettings.EstateID;
256 item.bannedIP = "0.0.0.0";
257 item.bannedIPHostMask = "0.0.0.0";
258
259 m_scene.RegionInfo.EstateSettings.AddBan(item);
260 m_scene.RegionInfo.EstateSettings.Save();
261
262 ScenePresence s = m_scene.GetScenePresence(user);
263 if (s != null)
264 {
265 if (!s.IsChildAgent)
266 {
267 s.ControllingClient.SendTeleportLocationStart();
268 m_scene.TeleportClientHome(user, s.ControllingClient);
269 }
270 }
271
272 }
273 else
274 {
275 remote_client.SendAlertMessage("User is already on the region ban list");
276 }
277 //m_scene.RegionInfo.regionBanlist.Add(Manager(user);
278 remote_client.SendBannedUserList(invoice, m_scene.RegionInfo.EstateSettings.EstateBans, m_scene.RegionInfo.EstateSettings.EstateID);
279 }
280 else
281 {
282 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
283 }
284 break;
285 case 128:
286 if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || m_scene.Permissions.BypassPermissions())
287 {
288 EstateBan[] banlistcheck = m_scene.RegionInfo.EstateSettings.EstateBans;
289
290 bool alreadyInList = false;
291 EstateBan listitem = null;
292
293 for (int i = 0; i < banlistcheck.Length; i++)
294 {
295 if (user == banlistcheck[i].bannedUUID)
296 {
297 alreadyInList = true;
298 listitem = banlistcheck[i];
299 break;
300 }
301
302 }
303 if (alreadyInList && listitem != null)
304 {
305 m_scene.RegionInfo.EstateSettings.RemoveBan(listitem.bannedUUID);
306 m_scene.RegionInfo.EstateSettings.Save();
307 }
308 else
309 {
310 remote_client.SendAlertMessage("User is not on the region ban list");
311 }
312 //m_scene.RegionInfo.regionBanlist.Add(Manager(user);
313 remote_client.SendBannedUserList(invoice, m_scene.RegionInfo.EstateSettings.EstateBans, m_scene.RegionInfo.EstateSettings.EstateID);
314 }
315 else
316 {
317 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
318 }
319 break;
320 case 256:
321
322 if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || m_scene.Permissions.BypassPermissions())
323 {
324 m_scene.RegionInfo.EstateSettings.AddEstateManager(user);
325 m_scene.RegionInfo.EstateSettings.Save();
326 remote_client.SendEstateManagersList(invoice, m_scene.RegionInfo.EstateSettings.EstateManagers, m_scene.RegionInfo.EstateSettings.EstateID);
327 }
328 else
329 {
330 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
331 }
332
333 break;
334 case 512:
335 if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || m_scene.Permissions.BypassPermissions())
336 {
337 m_scene.RegionInfo.EstateSettings.RemoveEstateManager(user);
338 m_scene.RegionInfo.EstateSettings.Save();
339
340 remote_client.SendEstateManagersList(invoice, m_scene.RegionInfo.EstateSettings.EstateManagers, m_scene.RegionInfo.EstateSettings.EstateID);
341 }
342 else
343 {
344 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
345 }
346 break;
347
348 default:
349
350 m_log.ErrorFormat("EstateOwnerMessage: Unknown EstateAccessType requested in estateAccessDelta: {0}", estateAccessType.ToString());
351 break;
352 }
353 }
354
355 private void SendSimulatorBlueBoxMessage(
356 IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message)
357 {
358 IDialogModule dm = m_scene.RequestModuleInterface<IDialogModule>();
359
360 if (dm != null)
361 dm.SendNotificationToUsersInRegion(senderID, senderName, message);
362 }
363
364 private void SendEstateBlueBoxMessage(
365 IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message)
366 {
367 IDialogModule dm = m_scene.RequestModuleInterface<IDialogModule>();
368
369 if (dm != null)
370 dm.SendNotificationToUsersInEstate(senderID, senderName, message);
371 }
372
373 private void handleEstateDebugRegionRequest(IClientAPI remote_client, UUID invoice, UUID senderID, bool scripted, bool collisionEvents, bool physics)
374 {
375 if (physics)
376 m_scene.RegionInfo.RegionSettings.DisablePhysics = true;
377 else
378 m_scene.RegionInfo.RegionSettings.DisablePhysics = false;
379
380 if (scripted)
381 m_scene.RegionInfo.RegionSettings.DisableScripts = true;
382 else
383 m_scene.RegionInfo.RegionSettings.DisableScripts = false;
384
385 if (collisionEvents)
386 m_scene.RegionInfo.RegionSettings.DisableCollisions = true;
387 else
388 m_scene.RegionInfo.RegionSettings.DisableCollisions = false;
389
390
391 m_scene.RegionInfo.RegionSettings.Save();
392
393 m_scene.SetSceneCoreDebug(scripted, collisionEvents, physics);
394 }
395
396 private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey)
397 {
398 if (prey != UUID.Zero)
399 {
400 ScenePresence s = m_scene.GetScenePresence(prey);
401 if (s != null)
402 {
403 s.ControllingClient.SendTeleportLocationStart();
404 m_scene.TeleportClientHome(prey, s.ControllingClient);
405 }
406 }
407 }
408
409 private void handleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID)
410 {
411 // Get a fresh list that will not change as people get teleported away
412 List<ScenePresence> prescences = m_scene.GetScenePresences();
413 foreach (ScenePresence p in prescences)
414 {
415 if (p.UUID != senderID)
416 {
417 // make sure they are still there, we could be working down a long list
418 ScenePresence s = m_scene.GetScenePresence(p.UUID);
419 if (s != null)
420 {
421 // Also make sure they are actually in the region
422 if (!s.IsChildAgent)
423 {
424 s.ControllingClient.SendTeleportLocationStart();
425 m_scene.TeleportClientHome(s.UUID, s.ControllingClient);
426 }
427 }
428 }
429 }
430 }
431 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID)
432 {
433 if (TerrainUploader != null)
434 {
435 lock (TerrainUploader)
436 {
437 if (XferID == TerrainUploader.XferID)
438 {
439 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
440 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
441 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
442
443 TerrainUploader = null;
444 remoteClient.SendAlertMessage("Terrain Upload aborted by the client");
445 }
446 }
447 }
448
449 }
450 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient)
451 {
452 lock (TerrainUploader)
453 {
454 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
455 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
456 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
457
458 TerrainUploader = null;
459 }
460 remoteClient.SendAlertMessage("Terrain Upload Complete. Loading....");
461 OpenSim.Region.Environment.Modules.World.Terrain.ITerrainModule terr = m_scene.RequestModuleInterface<OpenSim.Region.Environment.Modules.World.Terrain.ITerrainModule>();
462
463 if (terr != null)
464 {
465 m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + m_scene.RegionInfo.RegionName);
466 if (System.IO.File.Exists(Util.dataDir() + "/terrain.raw"))
467 {
468 System.IO.File.Delete(Util.dataDir() + "/terrain.raw");
469 }
470 try
471 {
472 System.IO.FileStream input = new System.IO.FileStream(Util.dataDir() + "/terrain.raw", System.IO.FileMode.CreateNew);
473 input.Write(terrainData, 0, terrainData.Length);
474 input.Close();
475 }
476 catch (System.IO.IOException e)
477 {
478 m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString());
479 remoteClient.SendAlertMessage("There was an IO Exception loading your terrain. Please check free space");
480
481 return;
482 }
483 catch (System.Security.SecurityException e)
484 {
485 m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString());
486 remoteClient.SendAlertMessage("There was a security Exception loading your terrain. Please check the security on the simulator drive");
487
488 return;
489 }
490 catch (System.UnauthorizedAccessException e)
491 {
492 m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString());
493 remoteClient.SendAlertMessage("There was a security Exception loading your terrain. Please check the security on the simulator drive");
494
495 return;
496 }
497
498
499
500
501 try
502 {
503 terr.LoadFromFile(Util.dataDir() + "/terrain.raw");
504 remoteClient.SendAlertMessage("Your terrain was loaded. Give it a minute or two to apply");
505 }
506 catch (Exception e)
507 {
508 m_log.ErrorFormat("[TERRAIN]: Error loading a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString());
509 remoteClient.SendAlertMessage("There was a general error loading your terrain. Please fix the terrain file and try again");
510 }
511
512 }
513 else
514 {
515 remoteClient.SendAlertMessage("Unable to apply terrain. Cannot get an instance of the terrain module");
516 }
517
518
519
520 }
521
522 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName)
523 {
524
525 if (TerrainUploader == null)
526 {
527
528 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
529 lock (TerrainUploader)
530 {
531 remote_client.OnXferReceive += TerrainUploader.XferReceive;
532 remote_client.OnAbortXfer += AbortTerrainXferHandler;
533 TerrainUploader.TerrainUploadDone += HandleTerrainApplication;
534 }
535 TerrainUploader.RequestStartXfer(remote_client);
536
537 }
538 else
539 {
540 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!");
541 }
542
543 }
544 private void handleTerrainRequest(IClientAPI remote_client, string clientFileName)
545 {
546 // Save terrain here
547 OpenSim.Region.Environment.Modules.World.Terrain.ITerrainModule terr = m_scene.RequestModuleInterface<OpenSim.Region.Environment.Modules.World.Terrain.ITerrainModule>();
548
549 if (terr != null)
550 {
551 m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + m_scene.RegionInfo.RegionName);
552 if (System.IO.File.Exists(Util.dataDir() + "/terrain.raw"))
553 {
554 System.IO.File.Delete(Util.dataDir() + "/terrain.raw");
555 }
556 terr.SaveToFile(Util.dataDir() + "/terrain.raw");
557
558 System.IO.FileStream input = new System.IO.FileStream(Util.dataDir() + "/terrain.raw", System.IO.FileMode.Open);
559 byte[] bdata = new byte[input.Length];
560 input.Read(bdata, 0, (int)input.Length);
561 remote_client.SendAlertMessage("Terrain file written, starting download...");
562 m_scene.XferManager.AddNewFile("terrain.raw", bdata);
563 // Tell client about it
564 m_log.Warn("[CLIENT]: Sending Terrain to " + remote_client.Name);
565 remote_client.SendInitiateDownload("terrain.raw", clientFileName);
566 }
567 }
568
569 private void HandleRegionInfoRequest(IClientAPI remote_client)
570 {
571 RegionInfoForEstateMenuArgs args = new RegionInfoForEstateMenuArgs();
572 args.billableFactor = m_scene.RegionInfo.EstateSettings.BillableFactor;
573 args.estateID = m_scene.RegionInfo.EstateSettings.EstateID;
574 args.maxAgents = (byte)m_scene.RegionInfo.RegionSettings.AgentLimit;
575 args.objectBonusFactor = (float)m_scene.RegionInfo.RegionSettings.ObjectBonus;
576 args.parentEstateID = m_scene.RegionInfo.EstateSettings.ParentEstateID;
577 args.pricePerMeter = m_scene.RegionInfo.EstateSettings.PricePerMeter;
578 args.redirectGridX = m_scene.RegionInfo.EstateSettings.RedirectGridX;
579 args.redirectGridY = m_scene.RegionInfo.EstateSettings.RedirectGridY;
580 args.regionFlags = GetRegionFlags();
581 byte mature = 13;
582 if (m_scene.RegionInfo.RegionSettings.Maturity == 1)
583 mature = 21;
584 args.simAccess = mature;
585
586 args.sunHour = (float)m_scene.RegionInfo.RegionSettings.SunPosition;
587 args.terrainLowerLimit = (float)m_scene.RegionInfo.RegionSettings.TerrainLowerLimit;
588 args.terrainRaiseLimit = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
589 args.useEstateSun = m_scene.RegionInfo.RegionSettings.UseEstateSun;
590 args.waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
591 args.simName = m_scene.RegionInfo.RegionName;
592
593 remote_client.SendRegionInfoToEstateMenu(args);
594 }
595
596 private void HandleEstateCovenantRequest(IClientAPI remote_client)
597 {
598 remote_client.SendEstateCovenantInformation(m_scene.RegionInfo.RegionSettings.Covenant);
599 }
600
601 private void HandleLandStatRequest(int parcelID, uint reportType, uint requestFlags, string filter, IClientAPI remoteClient)
602 {
603 Dictionary<uint, float> SceneData = new Dictionary<uint,float>();
604 List<UUID> uuidNameLookupList = new List<UUID>();
605
606 if (reportType == 1)
607 {
608 SceneData = m_scene.PhysicsScene.GetTopColliders();
609 }
610 else if (reportType == 0)
611 {
612 SceneData = m_scene.m_sceneGraph.GetTopScripts();
613 }
614
615 List<LandStatReportItem> SceneReport = new List<LandStatReportItem>();
616 lock (SceneData)
617 {
618 foreach (uint obj in SceneData.Keys)
619 {
620 SceneObjectPart prt = m_scene.GetSceneObjectPart(obj);
621 if (prt != null)
622 {
623 if (prt.ParentGroup != null)
624 {
625 SceneObjectGroup sog = prt.ParentGroup;
626 if (sog != null)
627 {
628 LandStatReportItem lsri = new LandStatReportItem();
629 lsri.LocationX = sog.AbsolutePosition.X;
630 lsri.LocationY = sog.AbsolutePosition.Y;
631 lsri.LocationZ = sog.AbsolutePosition.Z;
632 lsri.Score = SceneData[obj];
633 lsri.TaskID = sog.UUID;
634 lsri.TaskLocalID = sog.LocalId;
635 lsri.TaskName = sog.GetPartName(obj);
636 if (m_scene.CommsManager.UUIDNameCachedTest(sog.OwnerID))
637 {
638 lsri.OwnerName = m_scene.CommsManager.UUIDNameRequestString(sog.OwnerID);
639 }
640 else
641 {
642 lsri.OwnerName = "waiting";
643 lock (uuidNameLookupList)
644 uuidNameLookupList.Add(sog.OwnerID);
645 }
646
647 if (filter.Length != 0)
648 {
649 if ((lsri.OwnerName.Contains(filter) || lsri.TaskName.Contains(filter)))
650 {
651 }
652 else
653 {
654 continue;
655 }
656 }
657
658 SceneReport.Add(lsri);
659 }
660 }
661 }
662
663 }
664 }
665 remoteClient.SendLandStatReply(reportType, requestFlags, (uint)SceneReport.Count,SceneReport.ToArray());
666
667 if (uuidNameLookupList.Count > 0)
668 LookupUUID(uuidNameLookupList);
669 }
670
671 private void LookupUUIDSCompleted(IAsyncResult iar)
672 {
673 LookupUUIDS icon = (LookupUUIDS)iar.AsyncState;
674 icon.EndInvoke(iar);
675 }
676 private void LookupUUID(List<UUID> uuidLst)
677 {
678 LookupUUIDS d = LookupUUIDsAsync;
679
680 d.BeginInvoke(uuidLst,
681 LookupUUIDSCompleted,
682 d);
683 }
684 private void LookupUUIDsAsync(List<UUID> uuidLst)
685 {
686 UUID[] uuidarr = new UUID[0];
687
688 lock (uuidLst)
689 {
690 uuidarr = uuidLst.ToArray();
691 }
692
693 for (int i = 0; i < uuidarr.Length; i++)
694 {
695 // string lookupname = m_scene.CommsManager.UUIDNameRequestString(uuidarr[i]);
696 m_scene.CommsManager.UUIDNameRequestString(uuidarr[i]);
697 // we drop it. It gets cached though... so we're ready for the next request.
698 }
699 }
700 #endregion
701
702 #region Outgoing Packets
703
704 public void sendRegionInfoPacketToAll()
705 {
706 List<ScenePresence> avatars = m_scene.GetAvatars();
707
708 for (int i = 0; i < avatars.Count; i++)
709 {
710 HandleRegionInfoRequest(avatars[i].ControllingClient); ;
711 }
712 }
713
714 public void sendRegionHandshake(IClientAPI remoteClient)
715 {
716 RegionHandshakeArgs args = new RegionHandshakeArgs();
717
718 args.isEstateManager = m_scene.RegionInfo.EstateSettings.IsEstateManager(remoteClient.AgentId);
719 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero && m_scene.RegionInfo.EstateSettings.EstateOwner == remoteClient.AgentId)
720 args.isEstateManager = true;
721
722 args.billableFactor = m_scene.RegionInfo.EstateSettings.BillableFactor;
723 args.terrainStartHeight0 = (float)m_scene.RegionInfo.RegionSettings.Elevation1SW;
724 args.terrainHeightRange0 = (float)m_scene.RegionInfo.RegionSettings.Elevation2SW;
725 args.terrainStartHeight1 = (float)m_scene.RegionInfo.RegionSettings.Elevation1NW;
726 args.terrainHeightRange1 = (float)m_scene.RegionInfo.RegionSettings.Elevation2NW;
727 args.terrainStartHeight2 = (float)m_scene.RegionInfo.RegionSettings.Elevation1SE;
728 args.terrainHeightRange2 = (float)m_scene.RegionInfo.RegionSettings.Elevation2SE;
729 args.terrainStartHeight3 = (float)m_scene.RegionInfo.RegionSettings.Elevation1NE;
730 args.terrainHeightRange3 = (float)m_scene.RegionInfo.RegionSettings.Elevation2NE;
731 byte mature = 13;
732 if (m_scene.RegionInfo.RegionSettings.Maturity == 1)
733 mature = 21;
734 args.simAccess = mature;
735 args.waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
736
737 args.regionFlags = GetRegionFlags();
738 args.regionName = m_scene.RegionInfo.RegionName;
739 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
740 args.SimOwner = m_scene.RegionInfo.EstateSettings.EstateOwner;
741 else
742 args.SimOwner = m_scene.RegionInfo.MasterAvatarAssignedUUID;
743
744 // Fudge estate owner
745 //if (m_scene.Permissions.IsGod(remoteClient.AgentId))
746 // args.SimOwner = remoteClient.AgentId;
747
748 args.terrainBase0 = UUID.Zero;
749 args.terrainBase1 = UUID.Zero;
750 args.terrainBase2 = UUID.Zero;
751 args.terrainBase3 = UUID.Zero;
752 args.terrainDetail0 = m_scene.RegionInfo.RegionSettings.TerrainTexture1;
753 args.terrainDetail1 = m_scene.RegionInfo.RegionSettings.TerrainTexture2;
754 args.terrainDetail2 = m_scene.RegionInfo.RegionSettings.TerrainTexture3;
755 args.terrainDetail3 = m_scene.RegionInfo.RegionSettings.TerrainTexture4;
756
757 remoteClient.SendRegionHandshake(m_scene.RegionInfo,args);
758 }
759
760 public void sendRegionHandshakeToAll()
761 {
762 m_scene.Broadcast(sendRegionHandshake);
763 }
764
765 public void handleEstateChangeInfo(IClientAPI remoteClient, UUID invoice, UUID senderID, UInt32 parms1, UInt32 parms2)
766 {
767 if (parms2 == 0)
768 {
769 m_scene.RegionInfo.EstateSettings.UseGlobalTime = true;
770 m_scene.RegionInfo.EstateSettings.SunPosition = 0.0;
771 }
772 else
773 {
774 m_scene.RegionInfo.EstateSettings.UseGlobalTime = false;
775 m_scene.RegionInfo.EstateSettings.SunPosition = (double)(parms2 - 0x1800)/1024.0;
776 }
777
778 if ((parms1 & 0x00000010) != 0)
779 m_scene.RegionInfo.EstateSettings.FixedSun = true;
780 else
781 m_scene.RegionInfo.EstateSettings.FixedSun = false;
782
783 if ((parms1 & 0x00008000) != 0)
784 m_scene.RegionInfo.EstateSettings.PublicAccess = true;
785 else
786 m_scene.RegionInfo.EstateSettings.PublicAccess = false;
787
788 if ((parms1 & 0x10000000) != 0)
789 m_scene.RegionInfo.EstateSettings.AllowVoice = true;
790 else
791 m_scene.RegionInfo.EstateSettings.AllowVoice = false;
792
793 if ((parms1 & 0x00100000) != 0)
794 m_scene.RegionInfo.EstateSettings.AllowDirectTeleport = true;
795 else
796 m_scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
797
798 if ((parms1 & 0x00800000) != 0)
799 m_scene.RegionInfo.EstateSettings.DenyAnonymous = true;
800 else
801 m_scene.RegionInfo.EstateSettings.DenyAnonymous = false;
802
803 if ((parms1 & 0x01000000) != 0)
804 m_scene.RegionInfo.EstateSettings.DenyIdentified = true;
805 else
806 m_scene.RegionInfo.EstateSettings.DenyIdentified = false;
807
808 if ((parms1 & 0x02000000) != 0)
809 m_scene.RegionInfo.EstateSettings.DenyTransacted = true;
810 else
811 m_scene.RegionInfo.EstateSettings.DenyTransacted = false;
812
813 if ((parms1 & 0x40000000) != 0)
814 m_scene.RegionInfo.EstateSettings.DenyMinors = true;
815 else
816 m_scene.RegionInfo.EstateSettings.DenyMinors = false;
817
818 m_scene.RegionInfo.EstateSettings.Save();
819
820 float sun = (float)m_scene.RegionInfo.RegionSettings.SunPosition;
821 if (m_scene.RegionInfo.RegionSettings.UseEstateSun)
822 {
823 sun = (float)m_scene.RegionInfo.EstateSettings.SunPosition;
824 if (m_scene.RegionInfo.EstateSettings.UseGlobalTime)
825 sun = m_scene.EventManager.GetSunLindenHour();
826 }
827
828 m_scene.EventManager.TriggerEstateToolsTimeUpdate(
829 m_scene.RegionInfo.RegionHandle,
830 m_scene.RegionInfo.EstateSettings.FixedSun ||
831 m_scene.RegionInfo.RegionSettings.FixedSun,
832 m_scene.RegionInfo.RegionSettings.UseEstateSun, sun);
833
834 sendDetailedEstateData(remoteClient, invoice);
835 }
836
837 #endregion
838
839 #region IRegionModule Members
840
841 public void Initialise(Scene scene, IConfigSource source)
842 {
843 m_scene = scene;
844 m_scene.RegisterModuleInterface<IEstateModule>(this);
845 m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
846 m_scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight;
847 }
848
849
850 public void PostInitialise()
851 {
852 }
853
854 public void Close()
855 {
856 }
857
858 public string Name
859 {
860 get { return "EstateManagementModule"; }
861 }
862
863 public bool IsSharedModule
864 {
865 get { return false; }
866 }
867
868 #endregion
869
870 #region Other Functions
871
872 public void changeWaterHeight(float height)
873 {
874 setRegionTerrainSettings(height,
875 (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit,
876 (float)m_scene.RegionInfo.RegionSettings.TerrainLowerLimit,
877 m_scene.RegionInfo.RegionSettings.UseEstateSun,
878 m_scene.RegionInfo.RegionSettings.FixedSun,
879 (float)m_scene.RegionInfo.RegionSettings.SunPosition,
880 m_scene.RegionInfo.EstateSettings.UseGlobalTime,
881 m_scene.RegionInfo.EstateSettings.FixedSun,
882 (float)m_scene.RegionInfo.EstateSettings.SunPosition);
883
884 sendRegionInfoPacketToAll();
885 }
886
887 #endregion
888
889 private void EventManager_OnNewClient(IClientAPI client)
890 {
891 client.OnDetailedEstateDataRequest += sendDetailedEstateData;
892 client.OnSetEstateFlagsRequest += estateSetRegionInfoHandler;
893// client.OnSetEstateTerrainBaseTexture += setEstateTerrainBaseTexture;
894 client.OnSetEstateTerrainDetailTexture += setEstateTerrainBaseTexture;
895 client.OnSetEstateTerrainTextureHeights += setEstateTerrainTextureHeights;
896 client.OnCommitEstateTerrainTextureRequest += handleCommitEstateTerrainTextureRequest;
897 client.OnSetRegionTerrainSettings += setRegionTerrainSettings;
898 client.OnEstateRestartSimRequest += handleEstateRestartSimRequest;
899 client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest;
900 client.OnEstateChangeInfo += handleEstateChangeInfo;
901 client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest;
902 client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage;
903 client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage;
904 client.OnEstateDebugRegionRequest += handleEstateDebugRegionRequest;
905 client.OnEstateTeleportOneUserHomeRequest += handleEstateTeleportOneUserHomeRequest;
906 client.OnEstateTeleportAllUsersHomeRequest += handleEstateTeleportAllUsersHomeRequest;
907 client.OnRequestTerrain += handleTerrainRequest;
908 client.OnUploadTerrain += handleUploadTerrain;
909
910 client.OnRegionInfoRequest += HandleRegionInfoRequest;
911 client.OnEstateCovenantRequest += HandleEstateCovenantRequest;
912 client.OnLandStatRequest += HandleLandStatRequest;
913 sendRegionHandshake(client);
914 }
915
916 public uint GetRegionFlags()
917 {
918 RegionFlags flags = RegionFlags.None;
919
920 // Fully implemented
921 //
922 if (m_scene.RegionInfo.RegionSettings.AllowDamage)
923 flags |= RegionFlags.AllowDamage;
924 if (m_scene.RegionInfo.RegionSettings.BlockTerraform)
925 flags |= RegionFlags.BlockTerraform;
926 if (!m_scene.RegionInfo.RegionSettings.AllowLandResell)
927 flags |= RegionFlags.BlockLandResell;
928 if (m_scene.RegionInfo.RegionSettings.DisableCollisions)
929 flags |= RegionFlags.SkipCollisions;
930 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
931 flags |= RegionFlags.SkipScripts;
932 if (m_scene.RegionInfo.RegionSettings.DisablePhysics)
933 flags |= RegionFlags.SkipPhysics;
934 if (m_scene.RegionInfo.RegionSettings.BlockFly)
935 flags |= RegionFlags.NoFly;
936 if (m_scene.RegionInfo.RegionSettings.RestrictPushing)
937 flags |= RegionFlags.RestrictPushObject;
938 if (m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide)
939 flags |= RegionFlags.AllowParcelChanges;
940 if (m_scene.RegionInfo.RegionSettings.BlockShowInSearch)
941 flags |= (RegionFlags)(1 << 29);
942
943 if (m_scene.RegionInfo.RegionSettings.FixedSun)
944 flags |= RegionFlags.SunFixed;
945 if (m_scene.RegionInfo.RegionSettings.Sandbox)
946 flags |= RegionFlags.Sandbox;
947
948 // Fudge these to always on, so the menu options activate
949 //
950 flags |= RegionFlags.AllowLandmark;
951 flags |= RegionFlags.AllowSetHome;
952
953 // TODO: SkipUpdateInterestList
954
955 // Omitted
956 //
957 // Omitted: NullLayer (what is that?)
958 // Omitted: SkipAgentAction (what does it do?)
959
960 return (uint)flags;
961 }
962
963 public uint GetEstateFlags()
964 {
965 RegionFlags flags = RegionFlags.None;
966
967 if (m_scene.RegionInfo.EstateSettings.FixedSun)
968 flags |= RegionFlags.SunFixed;
969 if (m_scene.RegionInfo.EstateSettings.PublicAccess)
970 flags |= (RegionFlags.PublicAllowed |
971 RegionFlags.ExternallyVisible);
972 if (m_scene.RegionInfo.EstateSettings.AllowVoice)
973 flags |= RegionFlags.AllowVoice;
974 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
975 flags |= RegionFlags.AllowDirectTeleport;
976 if (m_scene.RegionInfo.EstateSettings.DenyAnonymous)
977 flags |= RegionFlags.DenyAnonymous;
978 if (m_scene.RegionInfo.EstateSettings.DenyIdentified)
979 flags |= RegionFlags.DenyIdentified;
980 if (m_scene.RegionInfo.EstateSettings.DenyTransacted)
981 flags |= RegionFlags.DenyTransacted;
982 if (m_scene.RegionInfo.EstateSettings.AbuseEmailToEstateOwner)
983 flags |= RegionFlags.AbuseEmailToEstateOwner;
984 if (m_scene.RegionInfo.EstateSettings.BlockDwell)
985 flags |= RegionFlags.BlockDwell;
986 if (m_scene.RegionInfo.EstateSettings.EstateSkipScripts)
987 flags |= RegionFlags.EstateSkipScripts;
988 if (m_scene.RegionInfo.EstateSettings.ResetHomeOnTeleport)
989 flags |= RegionFlags.ResetHomeOnTeleport;
990 if (m_scene.RegionInfo.EstateSettings.TaxFree)
991 flags |= RegionFlags.TaxFree;
992 if (m_scene.RegionInfo.EstateSettings.DenyMinors)
993 flags |= (RegionFlags)(1 << 30);
994
995 return (uint)flags;
996 }
997
998 public bool IsManager(UUID avatarID)
999 {
1000 if (avatarID == m_scene.RegionInfo.MasterAvatarAssignedUUID)
1001 return true;
1002 if (avatarID == m_scene.RegionInfo.EstateSettings.EstateOwner)
1003 return true;
1004
1005 List<UUID> ems = new List<UUID>(m_scene.RegionInfo.EstateSettings.EstateManagers);
1006 if (ems.Contains(avatarID))
1007 return true;
1008
1009 return false;
1010 }
1011 }
1012}
diff --git a/OpenSim/Region/Environment/Modules/World/Estate/EstateTerrainXferHandler.cs b/OpenSim/Region/Environment/Modules/World/Estate/EstateTerrainXferHandler.cs
deleted file mode 100644
index 267178e..0000000
--- a/OpenSim/Region/Environment/Modules/World/Estate/EstateTerrainXferHandler.cs
+++ /dev/null
@@ -1,127 +0,0 @@
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 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 */
27
28using System;
29using System.IO;
30using System.Reflection;
31using log4net;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications.Cache;
35using OpenSim.Region.Framework.Scenes;
36
37
38namespace OpenSim.Region.Environment.Modules.World.Estate
39{
40
41 public class EstateTerrainXferHandler
42 {
43 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 private AssetBase m_asset;
46
47 public delegate void TerrainUploadComplete(string name, byte[] filedata, IClientAPI remoteClient);
48
49 public event TerrainUploadComplete TerrainUploadDone;
50
51 //private string m_description = String.Empty;
52 //private string m_name = String.Empty;
53 //private UUID TransactionID = UUID.Zero;
54 private sbyte type = 0;
55
56 public ulong mXferID;
57 private TerrainUploadComplete handlerTerrainUploadDone;
58
59 public EstateTerrainXferHandler(IClientAPI pRemoteClient, string pClientFilename)
60 {
61
62 m_asset = new AssetBase();
63 m_asset.Metadata.FullID = UUID.Zero;
64 m_asset.Metadata.Type = type;
65 m_asset.Data = new byte[0];
66 m_asset.Metadata.Name = pClientFilename;
67 m_asset.Metadata.Description = "empty";
68 m_asset.Metadata.Local = true;
69 m_asset.Metadata.Temporary = true;
70
71 }
72
73 public ulong XferID
74 {
75 get { return mXferID; }
76 }
77
78 public void RequestStartXfer(IClientAPI pRemoteClient)
79 {
80 mXferID = Util.GetNextXferID();
81 pRemoteClient.SendXferRequest(mXferID, m_asset.Metadata.Type, m_asset.Metadata.FullID, 0, Utils.StringToBytes(m_asset.Metadata.Name));
82 }
83
84 /// <summary>
85 /// Process transfer data received from the client.
86 /// </summary>
87 /// <param name="xferID"></param>
88 /// <param name="packetID"></param>
89 /// <param name="data"></param>
90 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
91 {
92 if (mXferID == xferID)
93 {
94 if (m_asset.Data.Length > 1)
95 {
96 byte[] destinationArray = new byte[m_asset.Data.Length + data.Length];
97 Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length);
98 Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length);
99 m_asset.Data = destinationArray;
100 }
101 else
102 {
103 byte[] buffer2 = new byte[data.Length - 4];
104 Array.Copy(data, 4, buffer2, 0, data.Length - 4);
105 m_asset.Data = buffer2;
106 }
107
108 remoteClient.SendConfirmXfer(xferID, packetID);
109
110 if ((packetID & 0x80000000) != 0)
111 {
112 SendCompleteMessage(remoteClient);
113
114 }
115 }
116 }
117
118 public void SendCompleteMessage(IClientAPI remoteClient)
119 {
120 handlerTerrainUploadDone = TerrainUploadDone;
121 if (handlerTerrainUploadDone != null)
122 {
123 handlerTerrainUploadDone(m_asset.Metadata.Name, m_asset.Data, remoteClient);
124 }
125 }
126 }
127}
diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs b/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs
deleted file mode 100644
index 76555d2..0000000
--- a/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs
+++ /dev/null
@@ -1,188 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes;
34
35namespace OpenSim.Region.Environment.Modules.World.Land
36{
37 public class LandChannel : ILandChannel
38 {
39 #region Constants
40
41 //Land types set with flags in ParcelOverlay.
42 //Only one of these can be used.
43 public const float BAN_LINE_SAFETY_HIEGHT = 100;
44 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 128; //Equals 10000000
45 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 64; //Equals 01000000
46
47 //RequestResults (I think these are right, they seem to work):
48 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land
49 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land
50
51 //ParcelSelectObjects
52 public const int LAND_SELECT_OBJECTS_GROUP = 4;
53 public const int LAND_SELECT_OBJECTS_OTHER = 8;
54 public const int LAND_SELECT_OBJECTS_OWNER = 2;
55 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101
56 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100
57 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010
58 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001
59 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011
60 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000
61
62 //These are other constants. Yay!
63 public const int START_LAND_LOCAL_ID = 1;
64
65 #endregion
66
67 private readonly Scene m_scene;
68 private readonly LandManagementModule m_landManagementModule;
69
70 public LandChannel(Scene scene, LandManagementModule landManagementMod)
71 {
72 m_scene = scene;
73 m_landManagementModule = landManagementMod;
74 }
75
76 #region ILandChannel Members
77
78
79 /// <summary>
80 /// Get the land object at the specified point
81 /// </summary>
82 /// <param name="x_float">Value between 0 - 256 on the x axis of the point</param>
83 /// <param name="y_float">Value between 0 - 256 on the y axis of the point</param>
84 /// <returns>Land object at the point supplied</returns>
85 public ILandObject GetLandObject(float x_float, float y_float)
86 {
87 if (m_landManagementModule != null)
88 {
89 return m_landManagementModule.GetLandObject(x_float, y_float);
90 }
91 ILandObject obj = new LandObject(UUID.Zero, false, m_scene);
92 obj.landData.Name = "NO LAND";
93 return obj;
94 }
95
96 public ILandObject GetLandObject(int x, int y)
97 {
98 if (m_landManagementModule != null)
99 {
100 return m_landManagementModule.GetLandObject(x, y);
101 }
102 ILandObject obj = new LandObject(UUID.Zero, false, m_scene);
103 obj.landData.Name = "NO LAND";
104 return obj;
105 }
106
107 public List<ILandObject> AllParcels()
108 {
109 if (m_landManagementModule != null)
110 {
111 return m_landManagementModule.AllParcels();
112 }
113
114 return new List<ILandObject>();
115 }
116
117 public List<ILandObject> ParcelsNearPoint(Vector3 position)
118 {
119 if (m_landManagementModule != null)
120 {
121 return m_landManagementModule.ParcelsNearPoint(position);
122 }
123
124 return new List<ILandObject>();
125 }
126
127 public bool IsLandPrimCountTainted()
128 {
129 if (m_landManagementModule != null)
130 {
131 return m_landManagementModule.IsLandPrimCountTainted();
132 }
133
134 return false;
135 }
136
137 public bool IsForcefulBansAllowed()
138 {
139 if (m_landManagementModule != null)
140 {
141 return m_landManagementModule.AllowedForcefulBans;
142 }
143
144 return false;
145 }
146
147 public void UpdateLandObject(int localID, LandData data)
148 {
149 if (m_landManagementModule != null)
150 {
151 m_landManagementModule.UpdateLandObject(localID, data);
152 }
153 }
154 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
155 {
156 if (m_landManagementModule != null)
157 {
158 m_landManagementModule.ReturnObjectsInParcel(localID, returnType, agentIDs, taskIDs, remoteClient);
159 }
160 }
161
162 public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
163 {
164 if (m_landManagementModule != null)
165 {
166 m_landManagementModule.setParcelObjectMaxOverride(overrideDel);
167 }
168 }
169
170 public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
171 {
172 if (m_landManagementModule != null)
173 {
174 m_landManagementModule.setSimulatorObjectMaxOverride(overrideDel);
175 }
176 }
177
178 public void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime)
179 {
180 if (m_landManagementModule != null)
181 {
182 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime);
183 }
184 }
185
186 #endregion
187 }
188}
diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs b/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs
deleted file mode 100644
index 58176e4..0000000
--- a/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs
+++ /dev/null
@@ -1,1347 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenMetaverse;
33using log4net;
34using Nini.Config;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework;
38using OpenSim.Framework.Servers;
39using OpenSim.Framework.Communications.Capabilities;
40using OpenSim.Region.Physics.Manager;
41using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
42
43namespace OpenSim.Region.Environment.Modules.World.Land
44{
45 // used for caching
46 internal class ExtendedLandData {
47 public LandData landData;
48 public ulong regionHandle;
49 public uint x, y;
50 }
51
52 public class LandManagementModule : IRegionModule
53 {
54 private static readonly ILog m_log =
55 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 private static readonly string remoteParcelRequestPath = "0009/";
58
59 private LandChannel landChannel;
60 private Scene m_scene;
61
62 private readonly int[,] m_landIDList = new int[64, 64];
63 private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
64
65 private bool m_landPrimCountTainted;
66 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
67
68 private bool m_allowedForcefulBans = true;
69
70 // caches ExtendedLandData
71 private Cache parcelInfoCache;
72
73 #region IRegionModule Members
74
75 public void Initialise(Scene scene, IConfigSource source)
76 {
77 m_scene = scene;
78 m_landIDList.Initialize();
79 landChannel = new LandChannel(scene, this);
80
81 parcelInfoCache = new Cache();
82 parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache
83 parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0);
84
85 m_scene.EventManager.OnParcelPrimCountAdd += AddPrimToLandPrimCounts;
86 m_scene.EventManager.OnParcelPrimCountUpdate += UpdateLandPrimCounts;
87 m_scene.EventManager.OnAvatarEnteringNewParcel += new EventManager.AvatarEnteringNewParcel(handleAvatarChangingParcel);
88 m_scene.EventManager.OnClientMovement += new EventManager.ClientMovement(handleAnyClientMovement);
89 m_scene.EventManager.OnValidateLandBuy += handleLandValidationRequest;
90 m_scene.EventManager.OnLandBuy += handleLandBuyRequest;
91 m_scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
92 m_scene.EventManager.OnSignificantClientMovement += handleSignificantClientMovement;
93 m_scene.EventManager.OnObjectBeingRemovedFromScene += RemovePrimFromLandPrimCounts;
94
95 m_scene.EventManager.OnNoticeNoLandDataFromStorage += this.NoLandDataFromStorage;
96 m_scene.EventManager.OnIncomingLandDataFromStorage += this.IncomingLandObjectsFromStorage;
97 m_scene.EventManager.OnSetAllowForcefulBan += this.SetAllowedForcefulBans;
98 m_scene.EventManager.OnRequestParcelPrimCountUpdate += this.PerformParcelPrimCountUpdate;
99 m_scene.EventManager.OnParcelPrimCountTainted += this.SetPrimsTainted;
100 m_scene.EventManager.OnRegisterCaps += this.OnRegisterCaps;
101
102 lock (m_scene)
103 {
104 m_scene.LandChannel = (ILandChannel) landChannel;
105 }
106 }
107
108 void EventManager_OnNewClient(IClientAPI client)
109 {
110 //Register some client events
111 client.OnParcelPropertiesRequest += new ParcelPropertiesRequest(handleParcelPropertiesRequest);
112 client.OnParcelDivideRequest += new ParcelDivideRequest(handleParcelDivideRequest);
113 client.OnParcelJoinRequest += new ParcelJoinRequest(handleParcelJoinRequest);
114 client.OnParcelPropertiesUpdateRequest += new ParcelPropertiesUpdateRequest(handleParcelPropertiesUpdateRequest);
115 client.OnParcelSelectObjects += new ParcelSelectObjects(handleParcelSelectObjectsRequest);
116 client.OnParcelObjectOwnerRequest += new ParcelObjectOwnerRequest(handleParcelObjectOwnersRequest);
117 client.OnParcelAccessListRequest += new ParcelAccessListRequest(handleParcelAccessRequest);
118 client.OnParcelAccessListUpdateRequest += new ParcelAccessListUpdateRequest(handleParcelAccessUpdateRequest);
119 client.OnParcelAbandonRequest += new ParcelAbandonRequest(handleParcelAbandonRequest);
120 client.OnParcelGodForceOwner += new ParcelGodForceOwner(handleParcelGodForceOwner);
121 client.OnParcelReclaim += new ParcelReclaim(handleParcelReclaim);
122 client.OnParcelInfoRequest += new ParcelInfoRequest(handleParcelInfo);
123 client.OnParcelDwellRequest += new ParcelDwellRequest(handleParcelDwell);
124 if (m_scene.Entities.ContainsKey(client.AgentId))
125 {
126 SendLandUpdate((ScenePresence)m_scene.Entities[client.AgentId], true);
127 SendParcelOverlay(client);
128 }
129 }
130
131 public void PostInitialise()
132 {
133 }
134
135 public void Close()
136 {
137 }
138
139 public string Name
140 {
141 get { return "LandManagementModule"; }
142 }
143
144 public bool IsSharedModule
145 {
146 get { return false; }
147 }
148
149 #endregion
150
151 #region Parcel Add/Remove/Get/Create
152
153 public void SetAllowedForcefulBans(bool forceful)
154 {
155 AllowedForcefulBans = forceful;
156 }
157
158 public void UpdateLandObject(int local_id, LandData data)
159 {
160 LandData newData = data.Copy();
161 newData.LocalID = local_id;
162
163 lock (m_landList)
164 {
165 if (m_landList.ContainsKey(local_id))
166 {
167 m_landList[local_id].landData = newData;
168 m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]);
169 }
170 }
171 }
172
173 public bool AllowedForcefulBans
174 {
175 get { return m_allowedForcefulBans; }
176 set { m_allowedForcefulBans = value; }
177 }
178
179 /// <summary>
180 /// Resets the sim to the default land object (full sim piece of land owned by the default user)
181 /// </summary>
182 public void ResetSimLandObjects()
183 {
184 //Remove all the land objects in the sim and add a blank, full sim land object set to public
185 lock (m_landList)
186 {
187 m_landList.Clear();
188 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
189 m_landIDList.Initialize();
190 }
191
192 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
193
194 fullSimParcel.setLandBitmap(fullSimParcel.getSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
195 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
196 fullSimParcel.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
197 else
198 fullSimParcel.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
199 fullSimParcel.landData.ClaimDate = Util.UnixTimeSinceEpoch();
200 AddLandObject(fullSimParcel);
201 }
202
203 public List<ILandObject> AllParcels()
204 {
205 lock (m_landList)
206 {
207 return new List<ILandObject>(m_landList.Values);
208 }
209 }
210
211 public List<ILandObject> ParcelsNearPoint(Vector3 position)
212 {
213 List<ILandObject> parcelsNear = new List<ILandObject>();
214 for (int x = -4; x <= 4; x += 4)
215 {
216 for (int y = -4; y <= 4; y += 4)
217 {
218 ILandObject check = GetLandObject(position.X + x, position.Y + y);
219 if (check != null)
220 {
221 if (!parcelsNear.Contains(check))
222 {
223 parcelsNear.Add(check);
224 }
225 }
226 }
227 }
228
229 return parcelsNear;
230 }
231
232 public void SendYouAreBannedNotice(ScenePresence avatar)
233 {
234 if (AllowedForcefulBans)
235 {
236 avatar.ControllingClient.SendAlertMessage(
237 "You are not allowed on this parcel because you are banned. Please go away.");
238
239 avatar.PhysicsActor.Position =
240 new PhysicsVector(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y,
241 avatar.lastKnownAllowedPosition.Z);
242 avatar.PhysicsActor.Velocity = new PhysicsVector(0, 0, 0);
243 }
244 else
245 {
246 avatar.ControllingClient.SendAlertMessage(
247 "You are not allowed on this parcel because you are banned; however, the grid administrator has disabled ban lines globally. Please obey the land owner's requests or you can be banned from the entire sim!");
248 }
249 }
250
251 public void handleAvatarChangingParcel(ScenePresence avatar, int localLandID, UUID regionID)
252 {
253 if (m_scene.RegionInfo.RegionID == regionID)
254 {
255 ILandObject parcelAvatarIsEntering;
256 lock (m_landList)
257 {
258 parcelAvatarIsEntering = m_landList[localLandID];
259 }
260
261 if (parcelAvatarIsEntering != null)
262 {
263 if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT)
264 {
265 if (parcelAvatarIsEntering.isBannedFromLand(avatar.UUID))
266 {
267 SendYouAreBannedNotice(avatar);
268 }
269 else if (parcelAvatarIsEntering.isRestrictedFromLand(avatar.UUID))
270 {
271 avatar.ControllingClient.SendAlertMessage(
272 "You are not allowed on this parcel because the land owner has restricted access. For now, you can enter, but please respect the land owner's decisions (or he can ban you!).");
273 }
274 else
275 {
276 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
277 }
278 }
279 else
280 {
281 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
282 }
283 }
284 }
285 }
286
287 public void SendOutNearestBanLine(IClientAPI avatar)
288 {
289 List<ScenePresence> avatars = m_scene.GetAvatars();
290 foreach (ScenePresence presence in avatars)
291 {
292 if (presence.UUID == avatar.AgentId)
293 {
294 List<ILandObject> checkLandParcels = ParcelsNearPoint(presence.AbsolutePosition);
295 foreach (ILandObject checkBan in checkLandParcels)
296 {
297 if (checkBan.isBannedFromLand(avatar.AgentId))
298 {
299 checkBan.sendLandProperties((int)ParcelStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar);
300 return; //Only send one
301 }
302 if (checkBan.isRestrictedFromLand(avatar.AgentId))
303 {
304 checkBan.sendLandProperties((int)ParcelStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar);
305 return; //Only send one
306 }
307 }
308 return;
309 }
310 }
311 }
312
313 public void SendLandUpdate(ScenePresence avatar, bool force)
314 {
315 ILandObject over = GetLandObject((int)Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
316 (int)Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
317
318 if (over != null)
319 {
320 if (force)
321 {
322 if (!avatar.IsChildAgent)
323 {
324 over.sendLandUpdateToClient(avatar.ControllingClient);
325 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.LocalID,
326 m_scene.RegionInfo.RegionID);
327 }
328 }
329
330 if (avatar.currentParcelUUID != over.landData.GlobalID)
331 {
332 if (!avatar.IsChildAgent)
333 {
334 over.sendLandUpdateToClient(avatar.ControllingClient);
335 avatar.currentParcelUUID = over.landData.GlobalID;
336 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.LocalID,
337 m_scene.RegionInfo.RegionID);
338 }
339 }
340 }
341 }
342
343 public void SendLandUpdate(ScenePresence avatar)
344 {
345 SendLandUpdate(avatar, false);
346 }
347
348 public void handleSignificantClientMovement(IClientAPI remote_client)
349 {
350 ScenePresence clientAvatar = m_scene.GetScenePresence(remote_client.AgentId);
351
352 if (clientAvatar != null)
353 {
354 SendLandUpdate(clientAvatar);
355 SendOutNearestBanLine(remote_client);
356 ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y);
357 if (parcel != null)
358 {
359 if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT &&
360 clientAvatar.sentMessageAboutRestrictedParcelFlyingDown)
361 {
362 handleAvatarChangingParcel(clientAvatar, parcel.landData.LocalID, m_scene.RegionInfo.RegionID);
363 //They are going below the safety line!
364 if (!parcel.isBannedFromLand(clientAvatar.UUID))
365 {
366 clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false;
367 }
368 }
369 else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT &&
370 parcel.isBannedFromLand(clientAvatar.UUID))
371 {
372 SendYouAreBannedNotice(clientAvatar);
373 }
374 }
375 }
376 }
377
378 public void handleAnyClientMovement(ScenePresence avatar)
379 //Like handleSignificantClientMovement, but called with an AgentUpdate regardless of distance.
380 {
381 ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
382 if (over != null)
383 {
384 if (!over.isBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT)
385 {
386 avatar.lastKnownAllowedPosition =
387 new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
388 }
389 }
390 }
391
392
393 public void handleParcelAccessRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID,
394 int landLocalID, IClientAPI remote_client)
395 {
396 ILandObject land;
397 lock (m_landList)
398 {
399 m_landList.TryGetValue(landLocalID, out land);
400 }
401
402 if (land != null)
403 {
404 m_landList[landLocalID].sendAccessList(agentID, sessionID, flags, sequenceID, remote_client);
405 }
406 }
407
408 public void handleParcelAccessUpdateRequest(UUID agentID, UUID sessionID, uint flags, int landLocalID,
409 List<ParcelManager.ParcelAccessEntry> entries,
410 IClientAPI remote_client)
411 {
412 ILandObject land;
413 lock (m_landList)
414 {
415 m_landList.TryGetValue(landLocalID, out land);
416 }
417
418 if (land != null)
419 {
420 if (agentID == land.landData.OwnerID)
421 {
422 land.updateAccessList(flags, entries, remote_client);
423 }
424 }
425 else
426 {
427 m_log.WarnFormat("[LAND]: Invalid local land ID {0}", landLocalID);
428 }
429 }
430
431 /// <summary>
432 /// Creates a basic Parcel object without an owner (a zeroed key)
433 /// </summary>
434 /// <returns></returns>
435 public ILandObject CreateBaseLand()
436 {
437 return new LandObject(UUID.Zero, false, m_scene);
438 }
439
440 /// <summary>
441 /// Adds a land object to the stored list and adds them to the landIDList to what they own
442 /// </summary>
443 /// <param name="new_land">The land object being added</param>
444 public ILandObject AddLandObject(ILandObject land)
445 {
446 ILandObject new_land = land.Copy();
447
448 lock (m_landList)
449 {
450 int newLandLocalID = ++m_lastLandLocalID;
451 new_land.landData.LocalID = newLandLocalID;
452
453 bool[,] landBitmap = new_land.getLandBitmap();
454 for (int x = 0; x < 64; x++)
455 {
456 for (int y = 0; y < 64; y++)
457 {
458 if (landBitmap[x, y])
459 {
460 m_landIDList[x, y] = newLandLocalID;
461 }
462 }
463 }
464
465 m_landList.Add(newLandLocalID, new_land);
466 }
467
468 new_land.forceUpdateLandInfo();
469 m_scene.EventManager.TriggerLandObjectAdded(new_land);
470 return new_land;
471 }
472
473 /// <summary>
474 /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList
475 /// </summary>
476 /// <param name="local_id">Land.localID of the peice of land to remove.</param>
477 public void removeLandObject(int local_id)
478 {
479 lock (m_landList)
480 {
481 for (int x = 0; x < 64; x++)
482 {
483 for (int y = 0; y < 64; y++)
484 {
485 if (m_landIDList[x, y] == local_id)
486 {
487 m_log.WarnFormat("[LAND]: Not removing land object {0}; still being used at {1}, {2}",
488 local_id, x, y);
489 return;
490 //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y);
491 }
492 }
493 }
494
495 m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].landData.GlobalID);
496 m_landList.Remove(local_id);
497 }
498 }
499
500 private void performFinalLandJoin(ILandObject master, ILandObject slave)
501 {
502 bool[,] landBitmapSlave = slave.getLandBitmap();
503 lock (m_landList)
504 {
505 for (int x = 0; x < 64; x++)
506 {
507 for (int y = 0; y < 64; y++)
508 {
509 if (landBitmapSlave[x, y])
510 {
511 m_landIDList[x, y] = master.landData.LocalID;
512 }
513 }
514 }
515 }
516
517 removeLandObject(slave.landData.LocalID);
518 UpdateLandObject(master.landData.LocalID, master.landData);
519 }
520
521 public ILandObject GetLandObject(int parcelLocalID)
522 {
523 lock (m_landList)
524 {
525 if (m_landList.ContainsKey(parcelLocalID))
526 {
527 return m_landList[parcelLocalID];
528 }
529 }
530 return null;
531 }
532
533 /// <summary>
534 /// Get the land object at the specified point
535 /// </summary>
536 /// <param name="x_float">Value between 0 - 256 on the x axis of the point</param>
537 /// <param name="y_float">Value between 0 - 256 on the y axis of the point</param>
538 /// <returns>Land object at the point supplied</returns>
539 public ILandObject GetLandObject(float x_float, float y_float)
540 {
541 int x;
542 int y;
543
544 try
545 {
546 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0));
547 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0));
548 }
549 catch (OverflowException)
550 {
551 return null;
552 }
553
554 if (x >= 64 || y >= 64 || x < 0 || y < 0)
555 {
556 return null;
557 }
558 lock (m_landList)
559 {
560 // Corner case. If an autoreturn happens during sim startup
561 // we will come here with the list uninitialized
562 //
563 if (m_landList.ContainsKey(m_landIDList[x, y]))
564 return m_landList[m_landIDList[x, y]];
565 return null;
566 }
567 }
568
569 public ILandObject GetLandObject(int x, int y)
570 {
571 if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0)
572 {
573 // These exceptions here will cause a lot of complaints from the users specifically because
574 // they happen every time at border crossings
575 throw new Exception("Error: Parcel not found at point " + x + ", " + y);
576 }
577 lock (m_landIDList)
578 {
579 return m_landList[m_landIDList[x / 4, y / 4]];
580 }
581 }
582
583 #endregion
584
585 #region Parcel Modification
586
587 public void ResetAllLandPrimCounts()
588 {
589 lock (m_landList)
590 {
591 foreach (LandObject p in m_landList.Values)
592 {
593 p.resetLandPrimCounts();
594 }
595 }
596 }
597
598 public void SetPrimsTainted()
599 {
600 m_landPrimCountTainted = true;
601 }
602
603 public bool IsLandPrimCountTainted()
604 {
605 return m_landPrimCountTainted;
606 }
607
608 public void AddPrimToLandPrimCounts(SceneObjectGroup obj)
609 {
610 Vector3 position = obj.AbsolutePosition;
611 ILandObject landUnderPrim = GetLandObject(position.X, position.Y);
612 if (landUnderPrim != null)
613 {
614 landUnderPrim.addPrimToCount(obj);
615 }
616 }
617
618 public void RemovePrimFromLandPrimCounts(SceneObjectGroup obj)
619 {
620
621 lock (m_landList)
622 {
623 foreach (LandObject p in m_landList.Values)
624 {
625 p.removePrimFromCount(obj);
626 }
627 }
628 }
629
630 public void FinalizeLandPrimCountUpdate()
631 {
632 //Get Simwide prim count for owner
633 Dictionary<UUID, List<LandObject>> landOwnersAndParcels = new Dictionary<UUID, List<LandObject>>();
634 lock (m_landList)
635 {
636 foreach (LandObject p in m_landList.Values)
637 {
638 if (!landOwnersAndParcels.ContainsKey(p.landData.OwnerID))
639 {
640 List<LandObject> tempList = new List<LandObject>();
641 tempList.Add(p);
642 landOwnersAndParcels.Add(p.landData.OwnerID, tempList);
643 }
644 else
645 {
646 landOwnersAndParcels[p.landData.OwnerID].Add(p);
647 }
648 }
649 }
650
651 foreach (UUID owner in landOwnersAndParcels.Keys)
652 {
653 int simArea = 0;
654 int simPrims = 0;
655 foreach (LandObject p in landOwnersAndParcels[owner])
656 {
657 simArea += p.landData.Area;
658 simPrims += p.landData.OwnerPrims + p.landData.OtherPrims + p.landData.GroupPrims +
659 p.landData.SelectedPrims;
660 }
661
662 foreach (LandObject p in landOwnersAndParcels[owner])
663 {
664 p.landData.SimwideArea = simArea;
665 p.landData.SimwidePrims = simPrims;
666 }
667 }
668 }
669
670 public void UpdateLandPrimCounts()
671 {
672 ResetAllLandPrimCounts();
673 foreach (EntityBase obj in m_scene.Entities)
674 {
675 if (obj != null)
676 {
677 if ((obj is SceneObjectGroup) && !obj.IsDeleted && !((SceneObjectGroup) obj).IsAttachment)
678 {
679 m_scene.EventManager.TriggerParcelPrimCountAdd((SceneObjectGroup) obj);
680 }
681 }
682 }
683 FinalizeLandPrimCountUpdate();
684 m_landPrimCountTainted = false;
685 }
686
687 public void PerformParcelPrimCountUpdate()
688 {
689 ResetAllLandPrimCounts();
690 m_scene.EventManager.TriggerParcelPrimCountUpdate();
691 FinalizeLandPrimCountUpdate();
692 m_landPrimCountTainted = false;
693 }
694
695 /// <summary>
696 /// Subdivides a piece of land
697 /// </summary>
698 /// <param name="start_x">West Point</param>
699 /// <param name="start_y">South Point</param>
700 /// <param name="end_x">East Point</param>
701 /// <param name="end_y">North Point</param>
702 /// <param name="attempting_user_id">UUID of user who is trying to subdivide</param>
703 /// <returns>Returns true if successful</returns>
704 private void subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
705 {
706 //First, lets loop through the points and make sure they are all in the same peice of land
707 //Get the land object at start
708
709 ILandObject startLandObject = GetLandObject(start_x, start_y);
710
711 if (startLandObject == null) return;
712
713 //Loop through the points
714 try
715 {
716 int totalX = end_x - start_x;
717 int totalY = end_y - start_y;
718 for (int y = 0; y < totalY; y++)
719 {
720 for (int x = 0; x < totalX; x++)
721 {
722 ILandObject tempLandObject = GetLandObject(start_x + x, start_y + y);
723 if (tempLandObject == null) return;
724 if (tempLandObject != startLandObject) return;
725 }
726 }
727 }
728 catch (Exception)
729 {
730 return;
731 }
732
733 //If we are still here, then they are subdividing within one piece of land
734 //Check owner
735 if (!m_scene.Permissions.CanEditParcel(attempting_user_id, startLandObject))
736 {
737 return;
738 }
739
740 //Lets create a new land object with bitmap activated at that point (keeping the old land objects info)
741 ILandObject newLand = startLandObject.Copy();
742 newLand.landData.Name = "Subdivision of " + newLand.landData.Name;
743 newLand.landData.GlobalID = UUID.Random();
744
745 newLand.setLandBitmap(newLand.getSquareLandBitmap(start_x, start_y, end_x, end_y));
746
747 //Now, lets set the subdivision area of the original to false
748 int startLandObjectIndex = startLandObject.landData.LocalID;
749 lock (m_landList)
750 {
751 m_landList[startLandObjectIndex].setLandBitmap(
752 newLand.modifyLandBitmapSquare(startLandObject.getLandBitmap(), start_x, start_y, end_x, end_y, false));
753 m_landList[startLandObjectIndex].forceUpdateLandInfo();
754 }
755
756 SetPrimsTainted();
757
758 //Now add the new land object
759 ILandObject result = AddLandObject(newLand);
760 UpdateLandObject(startLandObject.landData.LocalID, startLandObject.landData);
761 result.sendLandUpdateToAvatarsOverMe();
762 }
763
764 /// <summary>
765 /// Join 2 land objects together
766 /// </summary>
767 /// <param name="start_x">x value in first piece of land</param>
768 /// <param name="start_y">y value in first piece of land</param>
769 /// <param name="end_x">x value in second peice of land</param>
770 /// <param name="end_y">y value in second peice of land</param>
771 /// <param name="attempting_user_id">UUID of the avatar trying to join the land objects</param>
772 /// <returns>Returns true if successful</returns>
773 private void join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
774 {
775 end_x -= 4;
776 end_y -= 4;
777
778 List<ILandObject> selectedLandObjects = new List<ILandObject>();
779 int stepYSelected;
780 for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4)
781 {
782 int stepXSelected;
783 for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4)
784 {
785 ILandObject p = GetLandObject(stepXSelected, stepYSelected);
786
787 if (p != null)
788 {
789 if (!selectedLandObjects.Contains(p))
790 {
791 selectedLandObjects.Add(p);
792 }
793 }
794 }
795 }
796 ILandObject masterLandObject = selectedLandObjects[0];
797 selectedLandObjects.RemoveAt(0);
798
799 if (selectedLandObjects.Count < 1)
800 {
801 return;
802 }
803 if (!m_scene.Permissions.CanEditParcel(attempting_user_id, masterLandObject))
804 {
805 return;
806 }
807 foreach (ILandObject p in selectedLandObjects)
808 {
809 if (p.landData.OwnerID != masterLandObject.landData.OwnerID)
810 {
811 return;
812 }
813 }
814
815 lock (m_landList)
816 {
817 foreach (ILandObject slaveLandObject in selectedLandObjects)
818 {
819 m_landList[masterLandObject.landData.LocalID].setLandBitmap(
820 slaveLandObject.mergeLandBitmaps(masterLandObject.getLandBitmap(), slaveLandObject.getLandBitmap()));
821 performFinalLandJoin(masterLandObject, slaveLandObject);
822 }
823 }
824 SetPrimsTainted();
825
826 masterLandObject.sendLandUpdateToAvatarsOverMe();
827 }
828
829 #endregion
830
831 #region Parcel Updating
832
833 /// <summary>
834 /// Where we send the ParcelOverlay packet to the client
835 /// </summary>
836 /// <param name="remote_client">The object representing the client</param>
837 public void SendParcelOverlay(IClientAPI remote_client)
838 {
839 const int LAND_BLOCKS_PER_PACKET = 1024;
840
841 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
842 int byteArrayCount = 0;
843 int sequenceID = 0;
844
845 for (int y = 0; y < 64; y++)
846 {
847 for (int x = 0; x < 64; x++)
848 {
849 byte tempByte = 0; //This represents the byte for the current 4x4
850
851 ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4);
852
853 if (currentParcelBlock != null)
854 {
855 if (currentParcelBlock.landData.OwnerID == remote_client.AgentId)
856 {
857 //Owner Flag
858 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
859 }
860 else if (currentParcelBlock.landData.SalePrice > 0 &&
861 (currentParcelBlock.landData.AuthBuyerID == UUID.Zero ||
862 currentParcelBlock.landData.AuthBuyerID == remote_client.AgentId))
863 {
864 //Sale Flag
865 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
866 }
867 else if (currentParcelBlock.landData.OwnerID == UUID.Zero)
868 {
869 //Public Flag
870 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
871 }
872 else
873 {
874 //Other Flag
875 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
876 }
877
878 //Now for border control
879
880 ILandObject westParcel = null;
881 ILandObject southParcel = null;
882 if (x > 0)
883 {
884 westParcel = GetLandObject((x - 1) * 4, y * 4);
885 }
886 if (y > 0)
887 {
888 southParcel = GetLandObject(x * 4, (y - 1) * 4);
889 }
890
891 if (x == 0)
892 {
893 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
894 }
895 else if (westParcel != null && westParcel != currentParcelBlock)
896 {
897 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
898 }
899
900 if (y == 0)
901 {
902 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
903 }
904 else if (southParcel != null && southParcel != currentParcelBlock)
905 {
906 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
907 }
908
909 byteArray[byteArrayCount] = tempByte;
910 byteArrayCount++;
911 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
912 {
913 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
914 byteArrayCount = 0;
915 sequenceID++;
916 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
917 }
918 }
919 }
920 }
921 }
922
923 public void handleParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
924 bool snap_selection, IClientAPI remote_client)
925 {
926 //Get the land objects within the bounds
927 List<ILandObject> temp = new List<ILandObject>();
928 int inc_x = end_x - start_x;
929 int inc_y = end_y - start_y;
930 for (int x = 0; x < inc_x; x++)
931 {
932 for (int y = 0; y < inc_y; y++)
933 {
934 ILandObject currentParcel = GetLandObject(start_x + x, start_y + y);
935
936 if (currentParcel != null)
937 {
938 if (!temp.Contains(currentParcel))
939 {
940 currentParcel.forceUpdateLandInfo();
941 temp.Add(currentParcel);
942 }
943 }
944 }
945 }
946
947 int requestResult = LandChannel.LAND_RESULT_SINGLE;
948 if (temp.Count > 1)
949 {
950 requestResult = LandChannel.LAND_RESULT_MULTIPLE;
951 }
952
953 for (int i = 0; i < temp.Count; i++)
954 {
955 temp[i].sendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
956 }
957
958 SendParcelOverlay(remote_client);
959 }
960
961 public void handleParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
962 {
963 ILandObject land;
964 lock (m_landList)
965 {
966 m_landList.TryGetValue(localID, out land);
967 }
968
969 if (land != null) land.updateLandProperties(args, remote_client);
970 }
971
972 public void handleParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client)
973 {
974 subdivide(west, south, east, north, remote_client.AgentId);
975 }
976
977 public void handleParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client)
978 {
979 join(west, south, east, north, remote_client.AgentId);
980 }
981
982 public void handleParcelSelectObjectsRequest(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
983 {
984 m_landList[local_id].sendForceObjectSelect(local_id, request_type, returnIDs, remote_client);
985 }
986
987 public void handleParcelObjectOwnersRequest(int local_id, IClientAPI remote_client)
988 {
989 ILandObject land;
990 lock (m_landList)
991 {
992 m_landList.TryGetValue(local_id, out land);
993 }
994
995 if (land != null)
996 {
997 m_landList[local_id].sendLandObjectOwners(remote_client);
998 }
999 else
1000 {
1001 m_log.WarnFormat("[PARCEL]: Invalid land object {0} passed for parcel object owner request", local_id);
1002 }
1003 }
1004
1005 public void handleParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client)
1006 {
1007 ILandObject land;
1008 lock (m_landList)
1009 {
1010 m_landList.TryGetValue(local_id, out land);
1011 }
1012
1013 if (land != null)
1014 {
1015 if (m_scene.Permissions.IsGod(remote_client.AgentId))
1016 {
1017 land.landData.OwnerID = ownerID;
1018
1019 m_scene.Broadcast(SendParcelOverlay);
1020 land.sendLandUpdateToClient(remote_client);
1021 }
1022 }
1023 }
1024
1025 public void handleParcelAbandonRequest(int local_id, IClientAPI remote_client)
1026 {
1027 ILandObject land;
1028 lock (m_landList)
1029 {
1030 m_landList.TryGetValue(local_id, out land);
1031 }
1032
1033 if (land != null)
1034 {
1035 if (m_scene.Permissions.CanAbandonParcel(remote_client.AgentId, land))
1036 {
1037 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
1038 land.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
1039 else
1040 land.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
1041 m_scene.Broadcast(SendParcelOverlay);
1042 land.sendLandUpdateToClient(remote_client);
1043 }
1044 }
1045 }
1046
1047 public void handleParcelReclaim(int local_id, IClientAPI remote_client)
1048 {
1049 ILandObject land;
1050 lock (m_landList)
1051 {
1052 m_landList.TryGetValue(local_id, out land);
1053 }
1054
1055 if (land != null)
1056 {
1057 if (m_scene.Permissions.CanReclaimParcel(remote_client.AgentId, land))
1058 {
1059 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
1060 land.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
1061 else
1062 land.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
1063 land.landData.ClaimDate = Util.UnixTimeSinceEpoch();
1064 m_scene.Broadcast(SendParcelOverlay);
1065 land.sendLandUpdateToClient(remote_client);
1066 }
1067 }
1068 }
1069 #endregion
1070
1071 // If the economy has been validated by the economy module,
1072 // and land has been validated as well, this method transfers
1073 // the land ownership
1074
1075 public void handleLandBuyRequest(Object o, EventManager.LandBuyArgs e)
1076 {
1077 if (e.economyValidated && e.landValidated)
1078 {
1079 ILandObject land;
1080 lock (m_landList)
1081 {
1082 m_landList.TryGetValue(e.parcelLocalID, out land);
1083 }
1084
1085 if (land != null)
1086 {
1087 land.updateLandSold(e.agentId, e.groupId, e.groupOwned, (uint)e.transactionID, e.parcelPrice, e.parcelArea);
1088 }
1089 }
1090 }
1091
1092 // After receiving a land buy packet, first the data needs to
1093 // be validated. This method validates the right to buy the
1094 // parcel
1095
1096 public void handleLandValidationRequest(Object o, EventManager.LandBuyArgs e)
1097 {
1098 if (e.landValidated == false)
1099 {
1100 ILandObject lob = null;
1101 lock (m_landList)
1102 {
1103 m_landList.TryGetValue(e.parcelLocalID, out lob);
1104 }
1105
1106 if (lob != null)
1107 {
1108 UUID AuthorizedID = lob.landData.AuthBuyerID;
1109 int saleprice = lob.landData.SalePrice;
1110 UUID pOwnerID = lob.landData.OwnerID;
1111
1112 bool landforsale = ((lob.landData.Flags &
1113 (uint)(Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects)) != 0);
1114 if ((AuthorizedID == UUID.Zero || AuthorizedID == e.agentId) && e.parcelPrice >= saleprice && landforsale)
1115 {
1116 // TODO I don't think we have to lock it here, no?
1117 //lock (e)
1118 //{
1119 e.parcelOwnerID = pOwnerID;
1120 e.landValidated = true;
1121 //}
1122 }
1123 }
1124 }
1125 }
1126
1127 #region Land Object From Storage Functions
1128
1129 public void IncomingLandObjectsFromStorage(List<LandData> data)
1130 {
1131 for (int i = 0; i < data.Count; i++)
1132 {
1133 IncomingLandObjectFromStorage(data[i]);
1134 }
1135 }
1136
1137 public void IncomingLandObjectFromStorage(LandData data)
1138 {
1139 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
1140 new_land.landData = data.Copy();
1141 new_land.setLandBitmapFromByteArray();
1142 AddLandObject(new_land);
1143 }
1144
1145 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
1146 {
1147 ILandObject selectedParcel = null;
1148 lock (m_landList)
1149 {
1150 m_landList.TryGetValue(localID, out selectedParcel);
1151 }
1152
1153 if (selectedParcel == null) return;
1154
1155 selectedParcel.returnLandObjects(returnType, agentIDs, taskIDs, remoteClient);
1156 }
1157
1158 public void NoLandDataFromStorage()
1159 {
1160 ResetSimLandObjects();
1161 }
1162
1163 #endregion
1164
1165 public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
1166 {
1167 lock (m_landList)
1168 {
1169 foreach (LandObject obj in m_landList.Values)
1170 {
1171 obj.setParcelObjectMaxOverride(overrideDel);
1172 }
1173 }
1174 }
1175
1176 public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
1177 {
1178 }
1179
1180 #region CAPS handler
1181
1182 private void OnRegisterCaps(UUID agentID, Caps caps)
1183 {
1184 string capsBase = "/CAPS/" + caps.CapsObjectPath;
1185 caps.RegisterHandler("RemoteParcelRequest",
1186 new RestStreamHandler("POST", capsBase + remoteParcelRequestPath,
1187 delegate(string request, string path, string param,
1188 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
1189 {
1190 return RemoteParcelRequest(request, path, param, agentID, caps);
1191 }));
1192 }
1193
1194 // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the
1195 // "real" parcelID, because we wouldn't be able to map that to the region the parcel belongs to.
1196 // So, we create a "fake" parcelID by using the regionHandle (64 bit), and the local (integer) x
1197 // and y coordinate (each 8 bit), encoded in a UUID (128 bit).
1198 //
1199 // Request format:
1200 // <llsd>
1201 // <map>
1202 // <key>location</key>
1203 // <array>
1204 // <real>1.23</real>
1205 // <real>45..6</real>
1206 // <real>78.9</real>
1207 // </array>
1208 // <key>region_id</key>
1209 // <uuid>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</uuid>
1210 // </map>
1211 // </llsd>
1212 private string RemoteParcelRequest(string request, string path, string param, UUID agentID, Caps caps)
1213 {
1214 UUID parcelID = UUID.Zero;
1215 try
1216 {
1217 Hashtable hash = new Hashtable();
1218 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
1219 if (hash.ContainsKey("region_id") && hash.ContainsKey("location"))
1220 {
1221 UUID regionID = (UUID)hash["region_id"];
1222 ArrayList list = (ArrayList)hash["location"];
1223 uint x = (uint)(double)list[0];
1224 uint y = (uint)(double)list[1];
1225 if (hash.ContainsKey("region_handle"))
1226 {
1227 // if you do a "About Landmark" on a landmark a second time, the viewer sends the
1228 // region_handle it got earlier via RegionHandleRequest
1229 ulong regionHandle = Util.BytesToUInt64Big((byte[])hash["region_handle"]);
1230 parcelID = Util.BuildFakeParcelID(regionHandle, x, y);
1231 }
1232 else if (regionID == m_scene.RegionInfo.RegionID)
1233 {
1234 // a parcel request for a local parcel => no need to query the grid
1235 parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y);
1236 }
1237 else
1238 {
1239 // a parcel request for a parcel in another region. Ask the grid about the region
1240 RegionInfo info = m_scene.CommsManager.GridService.RequestNeighbourInfo(regionID);
1241 if (info != null)
1242 parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y);
1243 }
1244 }
1245 }
1246 catch (LLSD.LLSDParseException e)
1247 {
1248 m_log.ErrorFormat("[LAND] Fetch error: {0}", e.Message);
1249 m_log.ErrorFormat("[LAND] ... in request {0}", request);
1250 }
1251 catch(InvalidCastException)
1252 {
1253 m_log.ErrorFormat("[LAND] Wrong type in request {0}", request);
1254 }
1255
1256 LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse();
1257 response.parcel_id = parcelID;
1258 m_log.DebugFormat("[LAND] got parcelID {0}", parcelID);
1259
1260 return LLSDHelpers.SerialiseLLSDReply(response);
1261 }
1262
1263 #endregion
1264
1265 private void handleParcelDwell(int localID, IClientAPI remoteClient)
1266 {
1267 ILandObject selectedParcel = null;
1268 lock (m_landList)
1269 {
1270 if (!m_landList.TryGetValue(localID, out selectedParcel))
1271 return;
1272 }
1273
1274 remoteClient.SendParcelDwellReply(localID, selectedParcel.landData.GlobalID, selectedParcel.landData.Dwell);
1275 }
1276
1277 private void handleParcelInfo(IClientAPI remoteClient, UUID parcelID)
1278 {
1279 if (parcelID == UUID.Zero)
1280 return;
1281
1282 ExtendedLandData data = (ExtendedLandData)parcelInfoCache.Get(parcelID, delegate(UUID parcel) {
1283 // assume we've got the parcelID we just computed in RemoteParcelRequest
1284 ExtendedLandData extLandData = new ExtendedLandData();
1285 Util.ParseFakeParcelID(parcel, out extLandData.regionHandle, out extLandData.x, out extLandData.y);
1286 m_log.DebugFormat("[LAND] got parcelinfo request for regionHandle {0}, x/y {1}/{2}",
1287 extLandData.regionHandle, extLandData.x, extLandData.y);
1288
1289 // for this region or for somewhere else?
1290 if (extLandData.regionHandle == m_scene.RegionInfo.RegionHandle)
1291 {
1292 extLandData.landData = this.GetLandObject(extLandData.x, extLandData.y).landData;
1293 }
1294 else
1295 {
1296 extLandData.landData = m_scene.CommsManager.GridService.RequestLandData(extLandData.regionHandle,
1297 extLandData.x,
1298 extLandData.y);
1299 if (extLandData.landData == null)
1300 {
1301 // we didn't find the region/land => don't cache
1302 return null;
1303 }
1304 }
1305 return extLandData;
1306 });
1307
1308 if (data != null) // if we found some data, send it
1309 {
1310 RegionInfo info;
1311 if (data.regionHandle == m_scene.RegionInfo.RegionHandle)
1312 {
1313 info = m_scene.RegionInfo;
1314 }
1315 else
1316 {
1317 // most likely still cached from building the extLandData entry
1318 info = m_scene.CommsManager.GridService.RequestNeighbourInfo(data.regionHandle);
1319 }
1320 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
1321 m_log.DebugFormat("[LAND] got parcelinfo for parcel {0} in region {1}; sending...",
1322 data.landData.Name, data.regionHandle);
1323 remoteClient.SendParcelInfo(info, data.landData, parcelID, data.x, data.y);
1324 }
1325 else
1326 m_log.Debug("[LAND] got no parcelinfo; not sending");
1327 }
1328
1329 public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime)
1330 {
1331 ILandObject land;
1332 lock (m_landList)
1333 {
1334 m_landList.TryGetValue(localID, out land);
1335 }
1336
1337 if (land == null) return;
1338
1339 if (!m_scene.Permissions.CanEditParcel(remoteClient.AgentId, land))
1340 return;
1341
1342 land.landData.OtherCleanTime = otherCleanTime;
1343
1344 UpdateLandObject(localID, land.landData);
1345 }
1346 }
1347}
diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandObject.cs b/OpenSim/Region/Environment/Modules/World/Land/LandObject.cs
deleted file mode 100644
index b5f7225..0000000
--- a/OpenSim/Region/Environment/Modules/World/Land/LandObject.cs
+++ /dev/null
@@ -1,930 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenMetaverse;
32using log4net;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36
37namespace OpenSim.Region.Environment.Modules.World.Land
38{
39 /// <summary>
40 /// Keeps track of a specific piece of land's information
41 /// </summary>
42 public class LandObject : ILandObject
43 {
44 #region Member Variables
45
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private bool[,] m_landBitmap = new bool[64,64];
48
49 protected LandData m_landData = new LandData();
50 protected Scene m_scene;
51 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
52
53 public bool[,] landBitmap
54 {
55 get { return m_landBitmap; }
56 set { m_landBitmap = value; }
57 }
58
59 #endregion
60
61 #region ILandObject Members
62
63 public LandData landData
64 {
65 get { return m_landData; }
66
67 set { m_landData = value; }
68 }
69
70 public UUID regionUUID
71 {
72 get { return m_scene.RegionInfo.RegionID; }
73 }
74
75 #region Constructors
76
77 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
78 {
79 m_scene = scene;
80 landData.OwnerID = owner_id;
81 landData.IsGroupOwned = is_group_owned;
82 }
83
84 #endregion
85
86 #region Member Functions
87
88 #region General Functions
89
90 /// <summary>
91 /// Checks to see if this land object contains a point
92 /// </summary>
93 /// <param name="x"></param>
94 /// <param name="y"></param>
95 /// <returns>Returns true if the piece of land contains the specified point</returns>
96 public bool containsPoint(int x, int y)
97 {
98 if (x >= 0 && y >= 0 && x <= Constants.RegionSize && x <= Constants.RegionSize)
99 {
100 return (landBitmap[x / 4, y / 4] == true);
101 }
102 else
103 {
104 return false;
105 }
106 }
107
108 public ILandObject Copy()
109 {
110 ILandObject newLand = new LandObject(landData.OwnerID, landData.IsGroupOwned, m_scene);
111
112 //Place all new variables here!
113 newLand.landBitmap = (bool[,]) (landBitmap.Clone());
114 newLand.landData = landData.Copy();
115
116 return newLand;
117 }
118
119
120 static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount;
121 static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount;
122
123 public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
124 {
125 overrideParcelMaxPrimCount = overrideDel;
126 }
127 public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
128 {
129 overrideSimulatorMaxPrimCount = overrideDel;
130 }
131
132 public int getParcelMaxPrimCount(ILandObject thisObject)
133 {
134 if (overrideParcelMaxPrimCount != null)
135 {
136 return overrideParcelMaxPrimCount(thisObject);
137 }
138 else
139 {
140 //Normal Calculations
141 return Convert.ToInt32(
142 Math.Round((Convert.ToDecimal(landData.Area) / Convert.ToDecimal(65536)) * m_scene.objectCapacity *
143 Convert.ToDecimal(m_scene.RegionInfo.RegionSettings.ObjectBonus))); ;
144 }
145 }
146 public int getSimulatorMaxPrimCount(ILandObject thisObject)
147 {
148 if (overrideSimulatorMaxPrimCount != null)
149 {
150 return overrideSimulatorMaxPrimCount(thisObject);
151 }
152 else
153 {
154 //Normal Calculations
155 return m_scene.objectCapacity;
156 }
157 }
158 #endregion
159
160 #region Packet Request Handling
161
162 public void sendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
163 {
164 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
165 uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
166 if (estateModule != null)
167 regionFlags = estateModule.GetRegionFlags();
168
169 // In a perfect world, this would have worked.
170 //
171// if ((landData.Flags & (uint)Parcel.ParcelFlags.AllowLandmark) != 0)
172// regionFlags |= (uint)RegionFlags.AllowLandmark;
173// if (landData.OwnerID == remote_client.AgentId)
174// regionFlags |= (uint)RegionFlags.AllowSetHome;
175 remote_client.SendLandProperties(sequence_id,
176 snap_selection, request_result, landData,
177 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
178 getParcelMaxPrimCount(this),
179 getSimulatorMaxPrimCount(this), regionFlags);
180 }
181
182 public void updateLandProperties(LandUpdateArgs args, IClientAPI remote_client)
183 {
184 if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this))
185 {
186 //Needs later group support
187 LandData newData = landData.Copy();
188
189 if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice)
190 {
191 if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this))
192 {
193 newData.AuthBuyerID = args.AuthBuyerID;
194 newData.SalePrice = args.SalePrice;
195 }
196 }
197 newData.Category = args.Category;
198 newData.Description = args.Desc;
199 newData.GroupID = args.GroupID;
200 newData.LandingType = args.LandingType;
201 newData.MediaAutoScale = args.MediaAutoScale;
202 newData.MediaID = args.MediaID;
203 newData.MediaURL = args.MediaURL;
204 newData.MusicURL = args.MusicURL;
205 newData.Name = args.Name;
206 newData.Flags = args.ParcelFlags;
207 newData.PassHours = args.PassHours;
208 newData.PassPrice = args.PassPrice;
209 newData.SnapshotID = args.SnapshotID;
210 newData.UserLocation = args.UserLocation;
211 newData.UserLookAt = args.UserLookAt;
212
213 m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData);
214
215 sendLandUpdateToAvatarsOverMe();
216 }
217 }
218
219 public void updateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
220 {
221 LandData newData = landData.Copy();
222 newData.OwnerID = avatarID;
223 newData.GroupID = groupID;
224 newData.IsGroupOwned = groupOwned;
225 //newData.auctionID = AuctionID;
226 newData.ClaimDate = Util.UnixTimeSinceEpoch();
227 newData.ClaimPrice = claimprice;
228 newData.SalePrice = 0;
229 newData.AuthBuyerID = UUID.Zero;
230 newData.Flags &= ~(uint) (Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects);
231 m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData);
232
233 sendLandUpdateToAvatarsOverMe();
234 }
235
236 public bool isEitherBannedOrRestricted(UUID avatar)
237 {
238 if (isBannedFromLand(avatar))
239 {
240 return true;
241 }
242 else if (isRestrictedFromLand(avatar))
243 {
244 return true;
245 }
246 return false;
247 }
248
249 public bool isBannedFromLand(UUID avatar)
250 {
251 if ((landData.Flags & (uint) Parcel.ParcelFlags.UseBanList) > 0)
252 {
253 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
254 entry.AgentID = avatar;
255 entry.Flags = AccessList.Ban;
256 entry.Time = new DateTime();
257 if (landData.ParcelAccessList.Contains(entry))
258 {
259 //They are banned, so lets send them a notice about this parcel
260 return true;
261 }
262 }
263 return false;
264 }
265
266 public bool isRestrictedFromLand(UUID avatar)
267 {
268 if ((landData.Flags & (uint) Parcel.ParcelFlags.UseAccessList) > 0)
269 {
270 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
271 entry.AgentID = avatar;
272 entry.Flags = AccessList.Access;
273 entry.Time = new DateTime();
274 if (!landData.ParcelAccessList.Contains(entry))
275 {
276 //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel
277 return true;
278 }
279 }
280 return false;
281 }
282
283 public void sendLandUpdateToClient(IClientAPI remote_client)
284 {
285 sendLandProperties(0, false, 0, remote_client);
286 }
287
288 public void sendLandUpdateToAvatarsOverMe()
289 {
290 List<ScenePresence> avatars = m_scene.GetAvatars();
291 ILandObject over = null;
292 for (int i = 0; i < avatars.Count; i++)
293 {
294 try
295 {
296 over =
297 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatars[i].AbsolutePosition.X), 0, 255),
298 Util.Clamp<int>((int)Math.Round(avatars[i].AbsolutePosition.Y), 0, 255));
299 }
300 catch (Exception)
301 {
302 m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatars[i].AbsolutePosition.X) + " y: " +
303 Math.Round(avatars[i].AbsolutePosition.Y));
304 }
305
306 if (over != null)
307 {
308 if (over.landData.LocalID == landData.LocalID)
309 {
310 if (((over.landData.Flags & (uint)Parcel.ParcelFlags.AllowDamage) != 0) && m_scene.RegionInfo.RegionSettings.AllowDamage)
311 avatars[i].Invulnerable = false;
312 else
313 avatars[i].Invulnerable = true;
314
315 sendLandUpdateToClient(avatars[i].ControllingClient);
316 }
317 }
318 }
319 }
320
321 #endregion
322
323 #region AccessList Functions
324
325 public List<UUID> createAccessListArrayByFlag(AccessList flag)
326 {
327 List<UUID> list = new List<UUID>();
328 foreach (ParcelManager.ParcelAccessEntry entry in landData.ParcelAccessList)
329 {
330 if (entry.Flags == flag)
331 {
332 list.Add(entry.AgentID);
333 }
334 }
335 if (list.Count == 0)
336 {
337 list.Add(UUID.Zero);
338 }
339
340 return list;
341 }
342
343 public void sendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID,
344 IClientAPI remote_client)
345 {
346
347 if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both)
348 {
349 List<UUID> avatars = createAccessListArrayByFlag(AccessList.Access);
350 remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,landData.LocalID);
351 }
352
353 if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both)
354 {
355 List<UUID> avatars = createAccessListArrayByFlag(AccessList.Ban);
356 remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, landData.LocalID);
357 }
358 }
359
360 public void updateAccessList(uint flags, List<ParcelManager.ParcelAccessEntry> entries, IClientAPI remote_client)
361 {
362 LandData newData = landData.Copy();
363
364 if (entries.Count == 1 && entries[0].AgentID == UUID.Zero)
365 {
366 entries.Clear();
367 }
368
369 List<ParcelManager.ParcelAccessEntry> toRemove = new List<ParcelManager.ParcelAccessEntry>();
370 foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList)
371 {
372 if (entry.Flags == (AccessList)flags)
373 {
374 toRemove.Add(entry);
375 }
376 }
377
378 foreach (ParcelManager.ParcelAccessEntry entry in toRemove)
379 {
380 newData.ParcelAccessList.Remove(entry);
381 }
382 foreach (ParcelManager.ParcelAccessEntry entry in entries)
383 {
384 ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry();
385 temp.AgentID = entry.AgentID;
386 temp.Time = new DateTime(); //Pointless? Yes.
387 temp.Flags = (AccessList)flags;
388
389 if (!newData.ParcelAccessList.Contains(temp))
390 {
391 newData.ParcelAccessList.Add(temp);
392 }
393 }
394
395 m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData);
396 }
397
398 #endregion
399
400 #region Update Functions
401
402 public void updateLandBitmapByteArray()
403 {
404 landData.Bitmap = convertLandBitmapToBytes();
405 }
406
407 /// <summary>
408 /// Update all settings in land such as area, bitmap byte array, etc
409 /// </summary>
410 public void forceUpdateLandInfo()
411 {
412 updateAABBAndAreaValues();
413 updateLandBitmapByteArray();
414 }
415
416 public void setLandBitmapFromByteArray()
417 {
418 landBitmap = convertBytesToLandBitmap();
419 }
420
421 /// <summary>
422 /// Updates the AABBMin and AABBMax values after area/shape modification of the land object
423 /// </summary>
424 private void updateAABBAndAreaValues()
425 {
426 int min_x = 64;
427 int min_y = 64;
428 int max_x = 0;
429 int max_y = 0;
430 int tempArea = 0;
431 int x, y;
432 for (x = 0; x < 64; x++)
433 {
434 for (y = 0; y < 64; y++)
435 {
436 if (landBitmap[x, y] == true)
437 {
438 if (min_x > x) min_x = x;
439 if (min_y > y) min_y = y;
440 if (max_x < x) max_x = x;
441 if (max_y < y) max_y = y;
442 tempArea += 16; //16sqm peice of land
443 }
444 }
445 }
446 int tx = min_x * 4;
447 if (tx > 255)
448 tx = 255;
449 int ty = min_y * 4;
450 if (ty > 255)
451 ty = 255;
452 landData.AABBMin =
453 new Vector3((float) (min_x * 4), (float) (min_y * 4),
454 (float) m_scene.Heightmap[tx, ty]);
455
456 tx = max_x * 4;
457 if (tx > 255)
458 tx = 255;
459 ty = max_y * 4;
460 if (ty > 255)
461 ty = 255;
462 landData.AABBMax =
463 new Vector3((float) (max_x * 4), (float) (max_y * 4),
464 (float) m_scene.Heightmap[tx, ty]);
465 landData.Area = tempArea;
466 }
467
468 #endregion
469
470 #region Land Bitmap Functions
471
472 /// <summary>
473 /// Sets the land's bitmap manually
474 /// </summary>
475 /// <param name="bitmap">64x64 block representing where this land is on a map</param>
476 public void setLandBitmap(bool[,] bitmap)
477 {
478 if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
479 {
480 //Throw an exception - The bitmap is not 64x64
481 //throw new Exception("Error: Invalid Parcel Bitmap");
482 }
483 else
484 {
485 //Valid: Lets set it
486 landBitmap = bitmap;
487 forceUpdateLandInfo();
488 }
489 }
490
491 /// <summary>
492 /// Gets the land's bitmap manually
493 /// </summary>
494 /// <returns></returns>
495 public bool[,] getLandBitmap()
496 {
497 return landBitmap;
498 }
499
500 /// <summary>
501 /// Full sim land object creation
502 /// </summary>
503 /// <returns></returns>
504 public bool[,] basicFullRegionLandBitmap()
505 {
506 return getSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize);
507 }
508
509 /// <summary>
510 /// Used to modify the bitmap between the x and y points. Points use 64 scale
511 /// </summary>
512 /// <param name="start_x"></param>
513 /// <param name="start_y"></param>
514 /// <param name="end_x"></param>
515 /// <param name="end_y"></param>
516 /// <returns></returns>
517 public bool[,] getSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
518 {
519 bool[,] tempBitmap = new bool[64,64];
520 tempBitmap.Initialize();
521
522 tempBitmap = modifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
523 return tempBitmap;
524 }
525
526 /// <summary>
527 /// Change a land bitmap at within a square and set those points to a specific value
528 /// </summary>
529 /// <param name="land_bitmap"></param>
530 /// <param name="start_x"></param>
531 /// <param name="start_y"></param>
532 /// <param name="end_x"></param>
533 /// <param name="end_y"></param>
534 /// <param name="set_value"></param>
535 /// <returns></returns>
536 public bool[,] modifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
537 bool set_value)
538 {
539 if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
540 {
541 //Throw an exception - The bitmap is not 64x64
542 //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
543 }
544
545 int x, y;
546 for (y = 0; y < 64; y++)
547 {
548 for (x = 0; x < 64; x++)
549 {
550 if (x >= start_x / 4 && x < end_x / 4
551 && y >= start_y / 4 && y < end_y / 4)
552 {
553 land_bitmap[x, y] = set_value;
554 }
555 }
556 }
557 return land_bitmap;
558 }
559
560 /// <summary>
561 /// Join the true values of 2 bitmaps together
562 /// </summary>
563 /// <param name="bitmap_base"></param>
564 /// <param name="bitmap_add"></param>
565 /// <returns></returns>
566 public bool[,] mergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
567 {
568 if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
569 {
570 //Throw an exception - The bitmap is not 64x64
571 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
572 }
573 if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
574 {
575 //Throw an exception - The bitmap is not 64x64
576 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
577 }
578
579 int x, y;
580 for (y = 0; y < 64; y++)
581 {
582 for (x = 0; x < 64; x++)
583 {
584 if (bitmap_add[x, y])
585 {
586 bitmap_base[x, y] = true;
587 }
588 }
589 }
590 return bitmap_base;
591 }
592
593 /// <summary>
594 /// Converts the land bitmap to a packet friendly byte array
595 /// </summary>
596 /// <returns></returns>
597 private byte[] convertLandBitmapToBytes()
598 {
599 byte[] tempConvertArr = new byte[512];
600 byte tempByte = 0;
601 int x, y, i, byteNum = 0;
602 i = 0;
603 for (y = 0; y < 64; y++)
604 {
605 for (x = 0; x < 64; x++)
606 {
607 tempByte = Convert.ToByte(tempByte | Convert.ToByte(landBitmap[x, y]) << (i++ % 8));
608 if (i % 8 == 0)
609 {
610 tempConvertArr[byteNum] = tempByte;
611 tempByte = (byte) 0;
612 i = 0;
613 byteNum++;
614 }
615 }
616 }
617 return tempConvertArr;
618 }
619
620 private bool[,] convertBytesToLandBitmap()
621 {
622 bool[,] tempConvertMap = new bool[64,64];
623 tempConvertMap.Initialize();
624 byte tempByte = 0;
625 int x = 0, y = 0, i = 0, bitNum = 0;
626 for (i = 0; i < 512; i++)
627 {
628 tempByte = landData.Bitmap[i];
629 for (bitNum = 0; bitNum < 8; bitNum++)
630 {
631 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
632 tempConvertMap[x, y] = bit;
633 x++;
634 if (x > 63)
635 {
636 x = 0;
637 y++;
638 }
639 }
640 }
641 return tempConvertMap;
642 }
643
644 #endregion
645
646 #region Object Select and Object Owner Listing
647
648 public void sendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
649 {
650 if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this))
651 {
652 List<uint> resultLocalIDs = new List<uint>();
653 try
654 {
655 lock (primsOverMe)
656 {
657 foreach (SceneObjectGroup obj in primsOverMe)
658 {
659 if (obj.LocalId > 0)
660 {
661 if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == landData.OwnerID)
662 {
663 resultLocalIDs.Add(obj.LocalId);
664 }
665 else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == landData.GroupID && landData.GroupID != UUID.Zero)
666 {
667 resultLocalIDs.Add(obj.LocalId);
668 }
669 else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER &&
670 obj.OwnerID != remote_client.AgentId)
671 {
672 resultLocalIDs.Add(obj.LocalId);
673 }
674 else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID))
675 {
676 resultLocalIDs.Add(obj.LocalId);
677 }
678 }
679 }
680 }
681 } catch (InvalidOperationException)
682 {
683 m_log.Error("[LAND]: Unable to force select the parcel objects. Arr.");
684 }
685
686 remote_client.SendForceClientSelectObjects(resultLocalIDs);
687 }
688 }
689
690 /// <summary>
691 /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
692 /// aggreagete details such as the number of prims.
693 ///
694 /// </summary>
695 /// <param name="remote_client">
696 /// A <see cref="IClientAPI"/>
697 /// </param>
698 public void sendLandObjectOwners(IClientAPI remote_client)
699 {
700 if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this))
701 {
702 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
703
704 lock (primsOverMe)
705 {
706 try
707 {
708
709 foreach (SceneObjectGroup obj in primsOverMe)
710 {
711 try
712 {
713 if (!primCount.ContainsKey(obj.OwnerID))
714 {
715 primCount.Add(obj.OwnerID, 0);
716 }
717 }
718 catch (NullReferenceException)
719 {
720 m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel");
721 }
722 try
723 {
724 primCount[obj.OwnerID] += obj.PrimCount;
725 }
726 catch (KeyNotFoundException)
727 {
728 m_log.Error("[LAND]: Unable to match a prim with it's owner.");
729 }
730 }
731 }
732 catch (InvalidOperationException)
733 {
734 m_log.Error("[LAND]: Unable to Enumerate Land object arr.");
735 }
736 }
737
738 remote_client.SendLandObjectOwners(primCount);
739 }
740 }
741
742 public Dictionary<UUID, int> getLandObjectOwners()
743 {
744 Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>();
745 lock (primsOverMe)
746 {
747 try
748 {
749
750 foreach (SceneObjectGroup obj in primsOverMe)
751 {
752 if (!ownersAndCount.ContainsKey(obj.OwnerID))
753 {
754 ownersAndCount.Add(obj.OwnerID, 0);
755 }
756 ownersAndCount[obj.OwnerID] += obj.PrimCount;
757 }
758 }
759 catch (InvalidOperationException)
760 {
761 m_log.Error("[LAND]: Unable to enumerate land owners. arr.");
762 }
763
764 }
765 return ownersAndCount;
766 }
767
768 #endregion
769
770 #region Object Returning
771
772 public void returnObject(SceneObjectGroup obj)
773 {
774 SceneObjectGroup[] objs = new SceneObjectGroup[1];
775 objs[0] = obj;
776 m_scene.returnObjects(objs, obj.OwnerID);
777 }
778
779 public void returnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
780 {
781 Dictionary<UUID,List<SceneObjectGroup>> returns =
782 new Dictionary<UUID,List<SceneObjectGroup>>();
783
784 lock (primsOverMe)
785 {
786 if (type == (uint)ObjectReturnType.Owner)
787 {
788 foreach (SceneObjectGroup obj in primsOverMe)
789 {
790 if (obj.OwnerID == m_landData.OwnerID)
791 {
792 if (!returns.ContainsKey(obj.OwnerID))
793 returns[obj.OwnerID] =
794 new List<SceneObjectGroup>();
795 returns[obj.OwnerID].Add(obj);
796 }
797 }
798 }
799 else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero)
800 {
801 foreach (SceneObjectGroup obj in primsOverMe)
802 {
803 if (obj.GroupID == m_landData.GroupID)
804 {
805 if (!returns.ContainsKey(obj.OwnerID))
806 returns[obj.OwnerID] =
807 new List<SceneObjectGroup>();
808 returns[obj.OwnerID].Add(obj);
809 }
810 }
811 }
812 else if (type == (uint)ObjectReturnType.Other)
813 {
814 foreach (SceneObjectGroup obj in primsOverMe)
815 {
816 if (obj.OwnerID != m_landData.OwnerID &&
817 (obj.GroupID != m_landData.GroupID ||
818 m_landData.GroupID == UUID.Zero))
819 {
820 if (!returns.ContainsKey(obj.OwnerID))
821 returns[obj.OwnerID] =
822 new List<SceneObjectGroup>();
823 returns[obj.OwnerID].Add(obj);
824 }
825 }
826 }
827 else if (type == (uint)ObjectReturnType.List)
828 {
829 List<UUID> ownerlist = new List<UUID>(owners);
830
831 foreach (SceneObjectGroup obj in primsOverMe)
832 {
833 if (ownerlist.Contains(obj.OwnerID))
834 {
835 if (!returns.ContainsKey(obj.OwnerID))
836 returns[obj.OwnerID] =
837 new List<SceneObjectGroup>();
838 returns[obj.OwnerID].Add(obj);
839 }
840 }
841 }
842 }
843
844 foreach (List<SceneObjectGroup> ol in returns.Values)
845 m_scene.returnObjects(ol.ToArray(), remote_client.AgentId);
846 }
847
848 #endregion
849
850 #region Object Adding/Removing from Parcel
851
852 public void resetLandPrimCounts()
853 {
854 landData.GroupPrims = 0;
855 landData.OwnerPrims = 0;
856 landData.OtherPrims = 0;
857 landData.SelectedPrims = 0;
858
859
860 lock (primsOverMe)
861 primsOverMe.Clear();
862 }
863
864 public void addPrimToCount(SceneObjectGroup obj)
865 {
866
867 UUID prim_owner = obj.OwnerID;
868 int prim_count = obj.PrimCount;
869
870 if (obj.IsSelected)
871 {
872 landData.SelectedPrims += prim_count;
873 }
874 else
875 {
876 if (prim_owner == landData.OwnerID)
877 {
878 landData.OwnerPrims += prim_count;
879 }
880 else if ((obj.GroupID == landData.GroupID ||
881 prim_owner == landData.GroupID) &&
882 landData.GroupID != UUID.Zero)
883 {
884 landData.GroupPrims += prim_count;
885 }
886 else
887 {
888 landData.OtherPrims += prim_count;
889 }
890 }
891
892 lock (primsOverMe)
893 primsOverMe.Add(obj);
894 }
895
896 public void removePrimFromCount(SceneObjectGroup obj)
897 {
898 lock (primsOverMe)
899 {
900 if (primsOverMe.Contains(obj))
901 {
902 UUID prim_owner = obj.OwnerID;
903 int prim_count = obj.PrimCount;
904
905 if (prim_owner == landData.OwnerID)
906 {
907 landData.OwnerPrims -= prim_count;
908 }
909 else if (obj.GroupID == landData.GroupID ||
910 prim_owner == landData.GroupID)
911 {
912 landData.GroupPrims -= prim_count;
913 }
914 else
915 {
916 landData.OtherPrims -= prim_count;
917 }
918
919 primsOverMe.Remove(obj);
920 }
921 }
922 }
923
924 #endregion
925
926 #endregion
927
928 #endregion
929 }
930}
diff --git a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
deleted file mode 100644
index 9165554..0000000
--- a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
+++ /dev/null
@@ -1,1060 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using OpenMetaverse;
32using OpenMetaverse.Packets;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Scenes;
35
36namespace OpenSim.Region.Environment.Modules.World.NPC
37{
38 public class NPCAvatar : IClientAPI
39 {
40 private readonly string m_firstname;
41 private readonly string m_lastname;
42 private readonly Vector3 m_startPos;
43 private readonly UUID m_uuid = UUID.Random();
44 private readonly Scene m_scene;
45
46
47 public NPCAvatar(string firstname, string lastname, Vector3 position, Scene scene)
48 {
49 m_firstname = firstname;
50 m_lastname = lastname;
51 m_startPos = position;
52 m_scene = scene;
53 }
54
55 public IScene Scene
56 {
57 get { return m_scene; }
58 }
59
60 public void Say(string message)
61 {
62 SendOnChatFromClient(message, ChatTypeEnum.Say);
63 }
64
65 public void Shout(string message)
66 {
67 SendOnChatFromClient(message, ChatTypeEnum.Shout);
68 }
69
70 public void Whisper(string message)
71 {
72 SendOnChatFromClient(message, ChatTypeEnum.Whisper);
73 }
74
75 public void Broadcast(string message)
76 {
77 SendOnChatFromClient(message, ChatTypeEnum.Broadcast);
78 }
79
80 public void GiveMoney(UUID target, int amount)
81 {
82 OnMoneyTransferRequest(m_uuid, target, amount, 1, "Payment");
83 }
84
85 public void InstantMessage(UUID target, string message)
86 {
87 OnInstantMessage(this, new GridInstantMessage(m_scene,
88 m_uuid, m_firstname + " " + m_lastname,
89 target, 0, false, message,
90 UUID.Zero, false, Position, new byte[0]));
91 }
92
93 public void SendAgentOffline(UUID[] agentIDs)
94 {
95
96 }
97
98 public void SendAgentOnline(UUID[] agentIDs)
99 {
100
101 }
102 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot,
103 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
104 {
105
106 }
107
108 public void SendAdminResponse(UUID Token, uint AdminLevel)
109 {
110
111 }
112
113 public void SendGroupMembership(GroupMembershipData[] GroupMembership)
114 {
115
116 }
117
118 public UUID GetDefaultAnimation(string name)
119 {
120 return UUID.Zero;
121 }
122
123 public Vector3 Position
124 {
125 get { return m_scene.Entities[m_uuid].AbsolutePosition; }
126 set { m_scene.Entities[m_uuid].AbsolutePosition = value; }
127 }
128
129 public bool SendLogoutPacketWhenClosing
130 {
131 set { }
132 }
133
134 #region Internal Functions
135
136 private void SendOnChatFromClient(string message, ChatTypeEnum chatType)
137 {
138 OSChatMessage chatFromClient = new OSChatMessage();
139 chatFromClient.Channel = 0;
140 chatFromClient.From = Name;
141 chatFromClient.Message = message;
142 chatFromClient.Position = StartPos;
143 chatFromClient.Scene = m_scene;
144 chatFromClient.Sender = this;
145 chatFromClient.SenderUUID = AgentId;
146 chatFromClient.Type = chatType;
147
148 OnChatFromClient(this, chatFromClient);
149 }
150
151 #endregion
152
153 #region Event Definitions IGNORE
154
155// disable warning: public events constituting public API
156#pragma warning disable 67
157 public event Action<IClientAPI> OnLogout;
158 public event ObjectPermissions OnObjectPermissions;
159
160 public event MoneyTransferRequest OnMoneyTransferRequest;
161 public event ParcelBuy OnParcelBuy;
162 public event Action<IClientAPI> OnConnectionClosed;
163 public event GenericMessage OnGenericMessage;
164 public event ImprovedInstantMessage OnInstantMessage;
165 public event ChatMessage OnChatFromClient;
166 public event TextureRequest OnRequestTexture;
167 public event RezObject OnRezObject;
168 public event ModifyTerrain OnModifyTerrain;
169 public event SetAppearance OnSetAppearance;
170 public event AvatarNowWearing OnAvatarNowWearing;
171 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
172 public event UUIDNameRequest OnDetachAttachmentIntoInv;
173 public event ObjectAttach OnObjectAttach;
174 public event ObjectDeselect OnObjectDetach;
175 public event ObjectDrop OnObjectDrop;
176 public event StartAnim OnStartAnim;
177 public event StopAnim OnStopAnim;
178 public event LinkObjects OnLinkObjects;
179 public event DelinkObjects OnDelinkObjects;
180 public event RequestMapBlocks OnRequestMapBlocks;
181 public event RequestMapName OnMapNameRequest;
182 public event TeleportLocationRequest OnTeleportLocationRequest;
183 public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
184 public event DisconnectUser OnDisconnectUser;
185 public event RequestAvatarProperties OnRequestAvatarProperties;
186 public event SetAlwaysRun OnSetAlwaysRun;
187
188 public event DeRezObject OnDeRezObject;
189 public event Action<IClientAPI> OnRegionHandShakeReply;
190 public event GenericCall2 OnRequestWearables;
191 public event GenericCall2 OnCompleteMovementToRegion;
192 public event UpdateAgent OnAgentUpdate;
193 public event AgentRequestSit OnAgentRequestSit;
194 public event AgentSit OnAgentSit;
195 public event AvatarPickerRequest OnAvatarPickerRequest;
196 public event Action<IClientAPI> OnRequestAvatarsData;
197 public event AddNewPrim OnAddPrim;
198 public event RequestGodlikePowers OnRequestGodlikePowers;
199 public event GodKickUser OnGodKickUser;
200 public event ObjectDuplicate OnObjectDuplicate;
201 public event GrabObject OnGrabObject;
202 public event ObjectSelect OnDeGrabObject;
203 public event MoveObject OnGrabUpdate;
204 public event ViewerEffectEventHandler OnViewerEffect;
205
206 public event FetchInventory OnAgentDataUpdateRequest;
207 public event TeleportLocationRequest OnSetStartLocationRequest;
208
209 public event UpdateShape OnUpdatePrimShape;
210 public event ObjectExtraParams OnUpdateExtraParams;
211 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
212 public event ObjectSelect OnObjectSelect;
213 public event GenericCall7 OnObjectDescription;
214 public event GenericCall7 OnObjectName;
215 public event GenericCall7 OnObjectClickAction;
216 public event GenericCall7 OnObjectMaterial;
217 public event UpdatePrimFlags OnUpdatePrimFlags;
218 public event UpdatePrimTexture OnUpdatePrimTexture;
219 public event UpdateVector OnUpdatePrimGroupPosition;
220 public event UpdateVector OnUpdatePrimSinglePosition;
221 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
222 public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
223 public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation;
224 public event UpdateVector OnUpdatePrimScale;
225 public event UpdateVector OnUpdatePrimGroupScale;
226 public event StatusChange OnChildAgentStatus;
227 public event GenericCall2 OnStopMovement;
228 public event Action<UUID> OnRemoveAvatar;
229
230 public event CreateNewInventoryItem OnCreateNewInventoryItem;
231 public event CreateInventoryFolder OnCreateNewInventoryFolder;
232 public event UpdateInventoryFolder OnUpdateInventoryFolder;
233 public event MoveInventoryFolder OnMoveInventoryFolder;
234 public event RemoveInventoryFolder OnRemoveInventoryFolder;
235 public event RemoveInventoryItem OnRemoveInventoryItem;
236 public event FetchInventoryDescendents OnFetchInventoryDescendents;
237 public event PurgeInventoryDescendents OnPurgeInventoryDescendents;
238 public event FetchInventory OnFetchInventory;
239 public event RequestTaskInventory OnRequestTaskInventory;
240 public event UpdateInventoryItem OnUpdateInventoryItem;
241 public event CopyInventoryItem OnCopyInventoryItem;
242 public event MoveInventoryItem OnMoveInventoryItem;
243 public event UDPAssetUploadRequest OnAssetUploadRequest;
244 public event XferReceive OnXferReceive;
245 public event RequestXfer OnRequestXfer;
246 public event AbortXfer OnAbortXfer;
247 public event ConfirmXfer OnConfirmXfer;
248 public event RezScript OnRezScript;
249 public event UpdateTaskInventory OnUpdateTaskInventory;
250 public event MoveTaskInventory OnMoveTaskItem;
251 public event RemoveTaskInventory OnRemoveTaskItem;
252 public event RequestAsset OnRequestAsset;
253
254 public event UUIDNameRequest OnNameFromUUIDRequest;
255 public event UUIDNameRequest OnUUIDGroupNameRequest;
256
257 public event ParcelPropertiesRequest OnParcelPropertiesRequest;
258 public event ParcelDivideRequest OnParcelDivideRequest;
259 public event ParcelJoinRequest OnParcelJoinRequest;
260 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
261 public event ParcelAbandonRequest OnParcelAbandonRequest;
262 public event ParcelGodForceOwner OnParcelGodForceOwner;
263 public event ParcelReclaim OnParcelReclaim;
264 public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest;
265 public event ParcelAccessListRequest OnParcelAccessListRequest;
266 public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest;
267 public event ParcelSelectObjects OnParcelSelectObjects;
268 public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest;
269 public event ObjectDeselect OnObjectDeselect;
270 public event RegionInfoRequest OnRegionInfoRequest;
271 public event EstateCovenantRequest OnEstateCovenantRequest;
272 public event RequestTerrain OnRequestTerrain;
273 public event RequestTerrain OnUploadTerrain;
274 public event ObjectDuplicateOnRay OnObjectDuplicateOnRay;
275
276 public event FriendActionDelegate OnApproveFriendRequest;
277 public event FriendActionDelegate OnDenyFriendRequest;
278 public event FriendshipTermination OnTerminateFriendship;
279
280 public event EconomyDataRequest OnEconomyDataRequest;
281 public event MoneyBalanceRequest OnMoneyBalanceRequest;
282 public event UpdateAvatarProperties OnUpdateAvatarProperties;
283
284 public event ObjectIncludeInSearch OnObjectIncludeInSearch;
285 public event UUIDNameRequest OnTeleportHomeRequest;
286
287 public event ScriptAnswer OnScriptAnswer;
288 public event RequestPayPrice OnRequestPayPrice;
289 public event ObjectSaleInfo OnObjectSaleInfo;
290 public event ObjectBuy OnObjectBuy;
291 public event BuyObjectInventory OnBuyObjectInventory;
292 public event AgentSit OnUndo;
293
294 public event ForceReleaseControls OnForceReleaseControls;
295 public event GodLandStatRequest OnLandStatRequest;
296 public event RequestObjectPropertiesFamily OnObjectGroupRequest;
297
298 public event DetailedEstateDataRequest OnDetailedEstateDataRequest;
299 public event SetEstateFlagsRequest OnSetEstateFlagsRequest;
300 public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture;
301 public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture;
302 public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights;
303 public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest;
304 public event SetRegionTerrainSettings OnSetRegionTerrainSettings;
305 public event BakeTerrain OnBakeTerrain;
306 public event EstateRestartSimRequest OnEstateRestartSimRequest;
307 public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
308 public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
309 public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
310 public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
311 public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
312 public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
313 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
314 public event EstateChangeInfo OnEstateChangeInfo;
315 public event ScriptReset OnScriptReset;
316 public event GetScriptRunning OnGetScriptRunning;
317 public event SetScriptRunning OnSetScriptRunning;
318 public event UpdateVector OnAutoPilotGo;
319
320 public event TerrainUnacked OnUnackedTerrain;
321
322 public event RegionHandleRequest OnRegionHandleRequest;
323 public event ParcelInfoRequest OnParcelInfoRequest;
324
325 public event ActivateGesture OnActivateGesture;
326 public event DeactivateGesture OnDeactivateGesture;
327 public event ObjectOwner OnObjectOwner;
328
329 public event DirPlacesQuery OnDirPlacesQuery;
330 public event DirFindQuery OnDirFindQuery;
331 public event DirLandQuery OnDirLandQuery;
332 public event DirPopularQuery OnDirPopularQuery;
333 public event DirClassifiedQuery OnDirClassifiedQuery;
334 public event EventInfoRequest OnEventInfoRequest;
335 public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime;
336
337 public event MapItemRequest OnMapItemRequest;
338
339 public event OfferCallingCard OnOfferCallingCard;
340 public event AcceptCallingCard OnAcceptCallingCard;
341 public event DeclineCallingCard OnDeclineCallingCard;
342 public event SoundTrigger OnSoundTrigger;
343
344 public event StartLure OnStartLure;
345 public event TeleportLureRequest OnTeleportLureRequest;
346 public event NetworkStats OnNetworkStatsUpdate;
347
348 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
349 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
350 public event ClassifiedDelete OnClassifiedDelete;
351 public event ClassifiedDelete OnClassifiedGodDelete;
352
353 public event EventNotificationAddRequest OnEventNotificationAddRequest;
354 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
355 public event EventGodDelete OnEventGodDelete;
356
357 public event ParcelDwellRequest OnParcelDwellRequest;
358
359 public event UserInfoRequest OnUserInfoRequest;
360 public event UpdateUserInfo OnUpdateUserInfo;
361
362#pragma warning restore 67
363
364 #endregion
365
366 public void ActivateGesture(UUID assetId, UUID gestureId)
367 {
368 }
369 public void DeactivateGesture(UUID assetId, UUID gestureId)
370 {
371 }
372
373 #region Overrriden Methods IGNORE
374
375 public virtual Vector3 StartPos
376 {
377 get { return m_startPos; }
378 set { }
379 }
380
381 public virtual UUID AgentId
382 {
383 get { return m_uuid; }
384 }
385
386 public UUID SessionId
387 {
388 get { return UUID.Zero; }
389 }
390
391 public UUID SecureSessionId
392 {
393 get { return UUID.Zero; }
394 }
395
396 public virtual string FirstName
397 {
398 get { return m_firstname; }
399 }
400
401 public virtual string LastName
402 {
403 get { return m_lastname; }
404 }
405
406 public virtual String Name
407 {
408 get { return FirstName + " " + LastName; }
409 }
410
411 public bool IsActive
412 {
413 get { return true; }
414 set { }
415 }
416
417 public UUID ActiveGroupId
418 {
419 get { return UUID.Zero; }
420 }
421
422 public string ActiveGroupName
423 {
424 get { return String.Empty; }
425 }
426
427 public ulong ActiveGroupPowers
428 {
429 get { return 0; }
430 }
431
432 public bool IsGroupMember(UUID groupID)
433 {
434 return false;
435 }
436
437 public ulong GetGroupPowers(UUID groupID)
438 {
439 return 0;
440 }
441
442 public virtual int NextAnimationSequenceNumber
443 {
444 get { return 1; }
445 }
446
447 public virtual void SendWearables(AvatarWearable[] wearables, int serial)
448 {
449 }
450
451 public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
452 {
453 }
454
455 public virtual void Kick(string message)
456 {
457 }
458
459 public virtual void SendStartPingCheck(byte seq)
460 {
461 }
462
463 public virtual void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List<AvatarPickerReplyDataArgs> Data)
464 {
465 }
466
467 public virtual void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle)
468 {
469
470 }
471
472 public virtual void SendKillObject(ulong regionHandle, uint localID)
473 {
474 }
475
476 public virtual void SetChildAgentThrottle(byte[] throttle)
477 {
478 }
479 public byte[] GetThrottlesPacked(float multiplier)
480 {
481 return new byte[0];
482 }
483
484
485 public virtual void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId)
486 {
487 }
488
489 public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName,
490 UUID fromAgentID, byte source, byte audible)
491 {
492 }
493
494 public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName,
495 UUID fromAgentID, byte source, byte audible)
496 {
497 }
498
499 public void SendInstantMessage(UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, uint timeStamp)
500 {
501
502 }
503
504 public void SendInstantMessage(UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, uint timeStamp, UUID transationID, bool fromGroup, byte[] binaryBucket)
505 {
506
507 }
508
509 public void SendGenericMessage(string method, List<string> message)
510 {
511
512 }
513
514 public virtual void SendLayerData(float[] map)
515 {
516 }
517
518 public virtual void SendLayerData(int px, int py, float[] map)
519 {
520 }
521 public virtual void SendLayerData(int px, int py, float[] map, bool track)
522 {
523 }
524
525 public virtual void SendWindData(Vector2[] windSpeeds) { }
526
527 public virtual void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
528 {
529 }
530
531 public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint)
532 {
533 }
534
535 public virtual AgentCircuitData RequestClientInfo()
536 {
537 return new AgentCircuitData();
538 }
539
540 public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt,
541 IPEndPoint newRegionExternalEndPoint, string capsURL)
542 {
543 }
544
545 public virtual void SendMapBlock(List<MapBlockData> mapBlocks, uint flag)
546 {
547 }
548
549 public virtual void SendLocalTeleport(Vector3 position, Vector3 lookAt, uint flags)
550 {
551 }
552
553 public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
554 uint locationID, uint flags, string capsURL)
555 {
556 }
557
558 public virtual void SendTeleportFailed(string reason)
559 {
560 }
561
562 public virtual void SendTeleportLocationStart()
563 {
564 }
565
566 public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance)
567 {
568 }
569
570 public virtual void SendPayPrice(UUID objectID, int[] payPrice)
571 {
572 }
573
574 public virtual void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID,
575 uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation)
576 {
577 }
578
579 public virtual void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID,
580 Vector3 position, Vector3 velocity, Quaternion rotation)
581 {
582 }
583
584 public virtual void SendCoarseLocationUpdate(List<Vector3> CoarseLocations)
585 {
586 }
587
588 public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
589 {
590 }
591
592 public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string msg, UUID textureID, int ch, string[] buttonlabels)
593 {
594 }
595
596 public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID,
597 PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel,
598 Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags,
599 UUID objectID, UUID ownerID, string text, byte[] color,
600 uint parentID,
601 byte[] particleSystem, byte clickAction, byte material)
602 {
603 }
604 public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID,
605 PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel,
606 Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags,
607 UUID objectID, UUID ownerID, string text, byte[] color,
608 uint parentID,
609 byte[] particleSystem, byte clickAction, byte material, byte[] textureanimation,
610 bool attachment, uint AttachmentPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius)
611 {
612 }
613 public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID,
614 Vector3 position, Quaternion rotation, Vector3 velocity,
615 Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint)
616 {
617 }
618
619 public virtual void SendInventoryFolderDetails(UUID ownerID, UUID folderID,
620 List<InventoryItemBase> items,
621 List<InventoryFolderBase> folders,
622 bool fetchFolders,
623 bool fetchItems)
624 {
625 }
626
627 public virtual void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item)
628 {
629 }
630
631 public virtual void SendInventoryItemCreateUpdate(InventoryItemBase Item)
632 {
633 }
634
635 public virtual void SendRemoveInventoryItem(UUID itemID)
636 {
637 }
638
639 /// <see>IClientAPI.SendBulkUpdateInventory(InventoryItemBase)</see>
640 public virtual void SendBulkUpdateInventory(InventoryItemBase item)
641 {
642 }
643
644 public virtual void SendBulkUpdateInventory(InventoryFolderBase folderBase)
645 {}
646
647 public void SendTakeControls(int controls, bool passToAgent, bool TakeControls)
648 {
649 }
650
651 public virtual void SendTaskInventory(UUID taskID, short serial, byte[] fileName)
652 {
653 }
654
655 public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data)
656 {
657 }
658
659 public virtual void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit,
660 int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor,
661 int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay,
662 int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent)
663 {
664
665 }
666 public virtual void SendNameReply(UUID profileId, string firstname, string lastname)
667 {
668 }
669
670 public virtual void SendPreLoadSound(UUID objectID, UUID ownerID, UUID soundID)
671 {
672 }
673
674 public virtual void SendPlayAttachedSound(UUID soundID, UUID objectID, UUID ownerID, float gain,
675 byte flags)
676 {
677 }
678
679 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
680 {
681 }
682
683 public void SendAttachedSoundGainChange(UUID objectID, float gain)
684 {
685
686 }
687
688 public void SendAlertMessage(string message)
689 {
690 }
691
692 public void SendAgentAlertMessage(string message, bool modal)
693 {
694 }
695
696 public void SendSystemAlertMessage(string message)
697 {
698 }
699
700 public void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message,
701 string url)
702 {
703 }
704
705 public virtual void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args)
706 {
707 if (OnRegionHandShakeReply != null)
708 {
709 OnRegionHandShakeReply(this);
710 }
711
712 if (OnCompleteMovementToRegion != null)
713 {
714 OnCompleteMovementToRegion();
715 }
716 }
717 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
718 {
719 }
720
721 public void SendConfirmXfer(ulong xferID, uint PacketID)
722 {
723 }
724
725 public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName)
726 {
727 }
728
729 public void SendInitiateDownload(string simFileName, string clientFileName)
730 {
731 }
732
733 public void SendImageFirstPart(ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec)
734 {
735 }
736
737 public void SendImageNotFound(UUID imageid)
738 {
739 }
740
741 public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData)
742 {
743 }
744
745 public void SendShutdownConnectionNotice()
746 {
747 }
748
749 public void SendSimStats(SimStats stats)
750 {
751 }
752
753 public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID,
754 uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask,
755 uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category,
756 UUID LastOwnerID, string ObjectName, string Description)
757 {
758 }
759
760 public void SendObjectPropertiesReply(UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID,
761 UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID,
762 UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName,
763 string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask,
764 uint BaseMask, byte saleType, int salePrice)
765 {
766 }
767
768 public bool AddMoney(int debit)
769 {
770 return false;
771 }
772
773 public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase)
774 {
775 }
776
777 public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks)
778 {
779 }
780
781 public void SendViewerTime(int phase)
782 {
783 }
784
785 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember,
786 string flAbout, uint flags, UUID flImageID, UUID imageID, string profileURL,
787 UUID partnerID)
788 {
789 }
790
791 public void SendAsset(AssetRequestToClient req)
792 {
793 }
794
795 public void SendTexture(AssetBase TextureAsset)
796 {
797 }
798
799 public void SetDebugPacketLevel(int newDebug)
800 {
801 }
802
803 public void InPacket(object NewPack)
804 {
805 }
806
807 public void ProcessInPacket(Packet NewPack)
808 {
809 }
810
811 public void Close(bool ShutdownCircuit)
812 {
813 }
814
815 public void Start()
816 {
817 }
818
819 public void Stop()
820 {
821 }
822
823 private uint m_circuitCode;
824
825 public uint CircuitCode
826 {
827 get { return m_circuitCode; }
828 set { m_circuitCode = value; }
829 }
830
831 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
832 {
833
834 }
835 public void SendLogoutPacket()
836 {
837 }
838
839 public void Terminate()
840 {
841 }
842
843 public ClientInfo GetClientInfo()
844 {
845 return null;
846 }
847
848 public void SetClientInfo(ClientInfo info)
849 {
850 }
851
852 public void SendScriptQuestion(UUID objectID, string taskName, string ownerName, UUID itemID, int question)
853 {
854 }
855 public void SendHealth(float health)
856 {
857 }
858
859 public void SendEstateManagersList(UUID invoice, UUID[] EstateManagers, uint estateID)
860 {
861 }
862
863 public void SendBannedUserList(UUID invoice, EstateBan[] banlist, uint estateID)
864 {
865 }
866
867 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
868 {
869 }
870 public void SendEstateCovenantInformation(UUID covenant)
871 {
872 }
873 public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner)
874 {
875 }
876
877 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor,int parcelObjectCapacity, int simObjectCapacity, uint regionFlags)
878 {
879 }
880 public void SendLandAccessListData(List<UUID> avatars, uint accessFlag, int localLandID)
881 {
882 }
883 public void SendForceClientSelectObjects(List<uint> objectIDs)
884 {
885 }
886 public void SendLandObjectOwners(Dictionary<UUID, int> ownersAndCount)
887 {
888 }
889 public void SendLandParcelOverlay(byte[] data, int sequence_id)
890 {
891 }
892
893 public void SendGroupNameReply(UUID groupLLUID, string GroupName)
894 {
895 }
896
897 public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running)
898 {
899 }
900
901 public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia)
902 {
903 }
904 #endregion
905
906
907 public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time)
908 {
909 }
910
911 public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID,
912 byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight,
913 byte mediaLoop)
914 {
915 }
916
917 public void SendSetFollowCamProperties (UUID objectID, SortedDictionary<int, float> parameters)
918 {
919 }
920
921 public void SendClearFollowCamProperties (UUID objectID)
922 {
923 }
924
925 public void SendRegionHandle (UUID regoinID, ulong handle)
926 {
927 }
928
929 public void SendParcelInfo (RegionInfo info, LandData land, UUID parcelID, uint x, uint y)
930 {
931 }
932
933 public void SetClientOption(string option, string value)
934 {
935 }
936
937 public string GetClientOption(string option)
938 {
939 return string.Empty;
940 }
941
942 public void SendScriptTeleportRequest (string objName, string simName, Vector3 pos, Vector3 lookAt)
943 {
944 }
945
946 public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data)
947 {
948 }
949
950 public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data)
951 {
952 }
953
954 public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data)
955 {
956 }
957
958 public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data)
959 {
960 }
961
962 public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data)
963 {
964 }
965
966 public void SendDirLandReply(UUID queryID, DirLandReplyData[] data)
967 {
968 }
969
970 public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data)
971 {
972 }
973
974 public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags)
975 {
976 }
977
978 public void KillEndDone()
979 {
980 }
981
982 public void SendEventInfoReply (EventData info)
983 {
984 }
985
986 public void SendOfferCallingCard (UUID destID, UUID transactionID)
987 {
988 }
989
990 public void SendAcceptCallingCard (UUID transactionID)
991 {
992 }
993
994 public void SendDeclineCallingCard (UUID transactionID)
995 {
996 }
997
998 public void SendJoinGroupReply(UUID groupID, bool success)
999 {
1000 }
1001
1002 public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success)
1003 {
1004 }
1005
1006 public void SendLeaveGroupReply(UUID groupID, bool success)
1007 {
1008 }
1009
1010 public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data)
1011 {
1012 }
1013
1014 public void SendTerminateFriend(UUID exFriendID)
1015 {
1016 }
1017
1018 #region IClientAPI Members
1019
1020
1021 public bool AddGenericPacketHandler(string MethodName, GenericMessage handler)
1022 {
1023 throw new NotImplementedException();
1024 }
1025
1026 public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name)
1027 {
1028 }
1029
1030 public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price)
1031 {
1032 }
1033
1034 public void SendAgentDropGroup(UUID groupID)
1035 {
1036 }
1037
1038 public void SendAvatarNotesReply(UUID targetID, string text)
1039 {
1040 }
1041
1042 public void SendAvatarPicksReply(UUID targetID, Dictionary<UUID, string> picks)
1043 {
1044 }
1045
1046 public void SendAvatarClassifiedReply(UUID targetID, Dictionary<UUID, string> classifieds)
1047 {
1048 }
1049
1050 public void SendParcelDwellReply(int localID, UUID parcelID, float dwell)
1051 {
1052 }
1053
1054 public void SendUserInfoReply(bool imViaEmail, bool visible, string email)
1055 {
1056 }
1057
1058 #endregion
1059 }
1060}
diff --git a/OpenSim/Region/Environment/Modules/World/NPC/NPCModule.cs b/OpenSim/Region/Environment/Modules/World/NPC/NPCModule.cs
deleted file mode 100644
index 2e7b16c..0000000
--- a/OpenSim/Region/Environment/Modules/World/NPC/NPCModule.cs
+++ /dev/null
@@ -1,68 +0,0 @@
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 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 */
27
28using OpenMetaverse;
29using Nini.Config;
30using OpenSim.Region.Framework.Interfaces;
31using OpenSim.Region.Framework.Scenes;
32
33namespace OpenSim.Region.Environment.Modules.World.NPC
34{
35 public class NPCModule : IRegionModule
36 {
37 // private const bool m_enabled = false;
38
39 public void Initialise(Scene scene, IConfigSource source)
40 {
41 // if (m_enabled)
42 // {
43 // NPCAvatar testAvatar = new NPCAvatar("Jack", "NPC", new Vector3(128, 128, 40), scene);
44 // NPCAvatar testAvatar2 = new NPCAvatar("Jill", "NPC", new Vector3(136, 128, 40), scene);
45 // scene.AddNewClient(testAvatar, false);
46 // scene.AddNewClient(testAvatar2, false);
47 // }
48 }
49
50 public void PostInitialise()
51 {
52 }
53
54 public void Close()
55 {
56 }
57
58 public string Name
59 {
60 get { return "NPCModule"; }
61 }
62
63 public bool IsSharedModule
64 {
65 get { return true; }
66 }
67 }
68}
diff --git a/OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs
deleted file mode 100644
index 8838e39..0000000
--- a/OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs
+++ /dev/null
@@ -1,1498 +0,0 @@
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 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 */
27
28using OpenMetaverse;
29using Nini.Config;
30using System;
31using System.Collections;
32using System.Collections.Generic;
33using System.Reflection;
34using log4net;
35using OpenSim;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.Environment.Modules.Framework;
40using OpenSim.Framework.Communications.Cache;
41
42namespace OpenSim.Region.Environment.Modules.World.Permissions
43{
44 public class PermissionsModule : IRegionModule
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 protected Scene m_scene;
49
50 #region Constants
51 // These are here for testing. They will be taken out
52
53 //private uint PERM_ALL = (uint)2147483647;
54 private uint PERM_COPY = (uint)32768;
55 //private uint PERM_MODIFY = (uint)16384;
56 private uint PERM_MOVE = (uint)524288;
57 //private uint PERM_TRANS = (uint)8192;
58 private uint PERM_LOCKED = (uint)540672;
59
60 /// <value>
61 /// Different user set names that come in from the configuration file.
62 /// </value>
63 enum UserSet
64 {
65 All,
66 Administrators
67 };
68
69 #endregion
70
71 #region Bypass Permissions / Debug Permissions Stuff
72
73 // Bypasses the permissions engine
74 private bool m_bypassPermissions = true;
75 private bool m_bypassPermissionsValue = true;
76 private bool m_propagatePermissions = false;
77 private bool m_debugPermissions = false;
78 private bool m_allowGridGods = false;
79 private bool m_RegionOwnerIsGod = false;
80 private bool m_ParcelOwnerIsGod = false;
81
82 /// <value>
83 /// The set of users that are allowed to create scripts. This is only active if permissions are not being
84 /// bypassed. This overrides normal permissions.
85 /// </value>
86 private UserSet m_allowedScriptCreators = UserSet.All;
87
88 /// <value>
89 /// The set of users that are allowed to edit (save) scripts. This is only active if
90 /// permissions are not being bypassed. This overrides normal permissions.-
91 /// </value>
92 private UserSet m_allowedScriptEditors = UserSet.All;
93
94 #endregion
95
96 #region IRegionModule Members
97
98 public void Initialise(Scene scene, IConfigSource config)
99 {
100 m_scene = scene;
101
102 IConfig myConfig = config.Configs["Startup"];
103
104 string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule");
105
106 List<string> modules=new List<string>(permissionModules.Split(','));
107
108 if (!modules.Contains("DefaultPermissionsModule"))
109 return;
110
111 m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false);
112 m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", true);
113 m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true);
114 m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true);
115 m_ParcelOwnerIsGod = myConfig.GetBoolean("parcel_owner_is_god", true);
116
117 m_allowedScriptCreators
118 = ParseUserSetConfigSetting(myConfig, "allowed_script_creators", m_allowedScriptCreators);
119 m_allowedScriptEditors
120 = ParseUserSetConfigSetting(myConfig, "allowed_script_editors", m_allowedScriptEditors);
121
122 if (m_bypassPermissions)
123 m_log.Info("[PERMISSIONS]: serviceside_object_permissions = false in ini file so disabling all region service permission checks");
124 else
125 m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks");
126
127 //Register functions with Scene External Checks!
128 m_scene.Permissions.AddBypassPermissionsHandler(BypassPermissions); //FULLY IMPLEMENTED
129 m_scene.Permissions.AddSetBypassPermissionsHandler(SetBypassPermissions); //FULLY IMPLEMENTED
130 m_scene.Permissions.AddPropagatePermissionsHandler(PropagatePermissions); //FULLY IMPLEMENTED
131 m_scene.Permissions.AddGenerateClientFlagsHandler(GenerateClientFlags); //NOT YET FULLY IMPLEMENTED
132 m_scene.Permissions.AddAbandonParcelHandler(CanAbandonParcel); //FULLY IMPLEMENTED
133 m_scene.Permissions.AddReclaimParcelHandler(CanReclaimParcel); //FULLY IMPLEMENTED
134 m_scene.Permissions.AddIsGodHandler(IsGod); //FULLY IMPLEMENTED
135 m_scene.Permissions.AddDuplicateObjectHandler(CanDuplicateObject); //FULLY IMPLEMENTED
136 m_scene.Permissions.AddDeleteObjectHandler(CanDeleteObject); //MAYBE FULLY IMPLEMENTED
137 m_scene.Permissions.AddEditObjectHandler(CanEditObject);//MAYBE FULLY IMPLEMENTED
138 m_scene.Permissions.AddEditParcelHandler(CanEditParcel); //FULLY IMPLEMENTED
139 m_scene.Permissions.AddInstantMessageHandler(CanInstantMessage); //FULLY IMPLEMENTED
140 m_scene.Permissions.AddInventoryTransferHandler(CanInventoryTransfer); //NOT YET IMPLEMENTED
141 m_scene.Permissions.AddIssueEstateCommandHandler(CanIssueEstateCommand); //FULLY IMPLEMENTED
142 m_scene.Permissions.AddMoveObjectHandler(CanMoveObject); //HOPEFULLY FULLY IMPLEMENTED
143 m_scene.Permissions.AddObjectEntryHandler(CanObjectEntry); //FULLY IMPLEMENTED
144 m_scene.Permissions.AddReturnObjectHandler(CanReturnObject); //NOT YET IMPLEMENTED
145 m_scene.Permissions.AddRezObjectHandler(CanRezObject); //HOPEFULLY FULLY IMPLEMENTED
146 m_scene.Permissions.AddRunConsoleCommandHandler(CanRunConsoleCommand); //FULLY IMPLEMENTED
147 m_scene.Permissions.AddRunScriptHandler(CanRunScript); //NOT YET IMPLEMENTED
148 m_scene.Permissions.AddSellParcelHandler(CanSellParcel); //FULLY IMPLEMENTED
149 m_scene.Permissions.AddTakeObjectHandler(CanTakeObject); //FULLY IMPLEMENTED
150 m_scene.Permissions.AddTakeCopyObjectHandler(CanTakeCopyObject); //FULLY IMPLEMENTED
151 m_scene.Permissions.AddTerraformLandHandler(CanTerraformLand); //FULL IMPLEMENTED (POINT ONLY!!! NOT AREA!!!)
152 m_scene.Permissions.AddCanLinkObjectHandler(CanLinkObject); //NOT YET IMPLEMENTED
153 m_scene.Permissions.AddCanDelinkObjectHandler(CanDelinkObject); //NOT YET IMPLEMENTED
154 m_scene.Permissions.AddCanBuyLandHandler(CanBuyLand); //NOT YET IMPLEMENTED
155
156 m_scene.Permissions.AddViewNotecardHandler(CanViewNotecard); //NOT YET IMPLEMENTED
157 m_scene.Permissions.AddViewScriptHandler(CanViewScript); //NOT YET IMPLEMENTED
158 m_scene.Permissions.AddEditNotecardHandler(CanEditNotecard); //NOT YET IMPLEMENTED
159 m_scene.Permissions.AddEditScriptHandler(CanEditScript); //NOT YET IMPLEMENTED
160
161 m_scene.Permissions.AddCanCreateObjectInventoryHandler(CanCreateObjectInventory); //NOT IMPLEMENTED HERE
162 m_scene.Permissions.AddEditObjectInventoryHandler(CanEditObjectInventory);//MAYBE FULLY IMPLEMENTED
163 m_scene.Permissions.AddCanCopyObjectInventoryHandler(CanCopyObjectInventory); //NOT YET IMPLEMENTED
164 m_scene.Permissions.AddCanDeleteObjectInventoryHandler(CanDeleteObjectInventory); //NOT YET IMPLEMENTED
165 m_scene.Permissions.AddResetScriptHandler(CanResetScript);
166
167 m_scene.Permissions.AddCanCreateUserInventoryHandler(CanCreateUserInventory); //NOT YET IMPLEMENTED
168 m_scene.Permissions.AddCanCopyUserInventoryHandler(CanCopyUserInventory); //NOT YET IMPLEMENTED
169 m_scene.Permissions.AddCanEditUserInventoryHandler(CanEditUserInventory); //NOT YET IMPLEMENTED
170 m_scene.Permissions.AddCanDeleteUserInventoryHandler(CanDeleteUserInventory); //NOT YET IMPLEMENTED
171
172 m_scene.Permissions.AddCanTeleportHandler(CanTeleport); //NOT YET IMPLEMENTED
173
174 m_scene.AddCommand("permissions", "bypass permissions",
175 "bypass permissions <true / false>",
176 "Bypass permission checks",
177 HandleBypassPermissions);
178
179 m_scene.AddCommand("permissions", "force permissions",
180 "force permissions <true / false>",
181 "Force permissions on or off",
182 HandleForcePermissions);
183
184 m_scene.AddCommand("permissions", "debug permissions",
185 "debug permissions <true / false>",
186 "Enable permissions debugging",
187 HandleDebugPermissions);
188 }
189
190 public void HandleBypassPermissions(string module, string[] args)
191 {
192 if (m_scene.ConsoleScene() != null &&
193 m_scene.ConsoleScene() != m_scene)
194 {
195 return;
196 }
197
198 if (args.Length > 2)
199 {
200 bool val;
201
202 if (!bool.TryParse(args[2], out val))
203 return;
204
205 m_bypassPermissions = val;
206
207 m_log.InfoFormat(
208 "[PERMISSIONS]: Set permissions bypass to {0} for {1}",
209 m_bypassPermissions, m_scene.RegionInfo.RegionName);
210 }
211 }
212
213 public void HandleForcePermissions(string module, string[] args)
214 {
215 if (m_scene.ConsoleScene() != null &&
216 m_scene.ConsoleScene() != m_scene)
217 {
218 return;
219 }
220
221 if (!m_bypassPermissions)
222 {
223 m_log.Error("[PERMISSIONS] Permissions can't be forced unless they are bypassed first");
224 return;
225 }
226
227 if (args.Length > 2)
228 {
229 bool val;
230
231 if (!bool.TryParse(args[2], out val))
232 return;
233
234 m_bypassPermissionsValue = val;
235
236 m_log.InfoFormat("[PERMISSIONS] Forced permissions to {0} in {1}", m_bypassPermissionsValue, m_scene.RegionInfo.RegionName);
237 }
238 }
239
240 public void HandleDebugPermissions(string module, string[] args)
241 {
242 if (m_scene.ConsoleScene() != null &&
243 m_scene.ConsoleScene() != m_scene)
244 {
245 return;
246 }
247
248 if (args.Length > 2)
249 {
250 bool val;
251
252 if (!bool.TryParse(args[2], out val))
253 return;
254
255 m_debugPermissions = val;
256
257 m_log.InfoFormat("[PERMISSIONS] Set permissions debugging to {0} in {1}", m_debugPermissions, m_scene.RegionInfo.RegionName);
258 }
259 }
260
261 public void PostInitialise()
262 {
263 }
264
265 public void Close()
266 {
267 }
268
269 public string Name
270 {
271 get { return "PermissionsModule"; }
272 }
273
274 public bool IsSharedModule
275 {
276 get { return false; }
277 }
278
279 #endregion
280
281 #region Helper Functions
282 protected void SendPermissionError(UUID user, string reason)
283 {
284 m_scene.EventManager.TriggerPermissionError(user, reason);
285 }
286
287 protected void DebugPermissionInformation(string permissionCalled)
288 {
289 if (m_debugPermissions)
290 m_log.Debug("[PERMISSIONS]: " + permissionCalled + " was called from " + m_scene.RegionInfo.RegionName);
291 }
292
293 /// <summary>
294 /// Parse a user set configuration setting
295 /// </summary>
296 /// <param name="config"></param>
297 /// <param name="settingName"></param>
298 /// <param name="defaultValue">The default value for this attribute</param>
299 /// <returns>The parsed value</returns>
300 private static UserSet ParseUserSetConfigSetting(IConfig config, string settingName, UserSet defaultValue)
301 {
302 UserSet userSet = defaultValue;
303
304 string rawSetting = config.GetString(settingName, defaultValue.ToString());
305
306 // Temporary measure to allow 'gods' to be specified in config for consistency's sake. In the long term
307 // this should disappear.
308 if ("gods" == rawSetting.ToLower())
309 rawSetting = UserSet.Administrators.ToString();
310
311 // Doing it this was so that we can do a case insensitive conversion
312 try
313 {
314 userSet = (UserSet)Enum.Parse(typeof(UserSet), rawSetting, true);
315 }
316 catch
317 {
318 m_log.ErrorFormat(
319 "[PERMISSIONS]: {0} is not a valid {1} value, setting to {2}",
320 rawSetting, settingName, userSet);
321 }
322
323 m_log.DebugFormat("[PERMISSIONS]: {0} {1}", settingName, userSet);
324
325 return userSet;
326 }
327
328 /// <summary>
329 /// Is the given user an administrator (in other words, a god)?
330 /// </summary>
331 /// <param name="user"></param>
332 /// <returns></returns>
333 protected bool IsAdministrator(UUID user)
334 {
335 if (m_scene.RegionInfo.MasterAvatarAssignedUUID != UUID.Zero)
336 {
337 if (m_RegionOwnerIsGod && (m_scene.RegionInfo.MasterAvatarAssignedUUID == user))
338 return true;
339 }
340
341 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
342 {
343 if (m_scene.RegionInfo.EstateSettings.EstateOwner == user)
344 return true;
345 }
346
347 if (m_allowGridGods)
348 {
349 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(user);
350 if (profile != null && profile.UserProfile != null)
351 {
352 if (profile.UserProfile.GodLevel >= 200)
353 return true;
354 }
355 else
356 {
357 m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for administrator check", user);
358 }
359 }
360
361 return false;
362 }
363
364 protected bool IsEstateManager(UUID user)
365 {
366 return m_scene.RegionInfo.EstateSettings.IsEstateManager(user);
367 }
368#endregion
369
370 public bool PropagatePermissions()
371 {
372 if (m_bypassPermissions)
373 return false;
374
375 return m_propagatePermissions;
376 }
377
378 public bool BypassPermissions()
379 {
380 return m_bypassPermissions;
381 }
382
383 public void SetBypassPermissions(bool value)
384 {
385 m_bypassPermissions=value;
386 }
387
388 #region Object Permissions
389
390 public uint GenerateClientFlags(UUID user, UUID objID)
391 {
392 // Here's the way this works,
393 // ObjectFlags and Permission flags are two different enumerations
394 // ObjectFlags, however, tells the client to change what it will allow the user to do.
395 // So, that means that all of the permissions type ObjectFlags are /temporary/ and only
396 // supposed to be set when customizing the objectflags for the client.
397
398 // These temporary objectflags get computed and added in this function based on the
399 // Permission mask that's appropriate!
400 // Outside of this method, they should never be added to objectflags!
401 // -teravus
402
403 SceneObjectPart task = m_scene.GetSceneObjectPart(objID);
404
405 // this shouldn't ever happen.. return no permissions/objectflags.
406 if (task == null)
407 return (uint)0;
408
409 uint objflags = task.GetEffectiveObjectFlags();
410 UUID objectOwner = task.OwnerID;
411
412
413 // Remove any of the objectFlags that are temporary. These will get added back if appropriate
414 // in the next bit of code
415
416 // libomv will moan about PrimFlags.ObjectYouOfficer being
417 // deprecated
418 #pragma warning disable 0612
419 objflags &= (uint)
420 ~(PrimFlags.ObjectCopy | // Tells client you can copy the object
421 PrimFlags.ObjectModify | // tells client you can modify the object
422 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
423 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
424 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
425 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
426 PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object
427 PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set
428 );
429 #pragma warning restore 0612
430
431 // Creating the three ObjectFlags options for this method to choose from.
432 // Customize the OwnerMask
433 uint objectOwnerMask = ApplyObjectModifyMasks(task.OwnerMask, objflags);
434 objectOwnerMask |= (uint)PrimFlags.ObjectYouOwner | (uint)PrimFlags.ObjectAnyOwner | (uint)PrimFlags.ObjectOwnerModify;
435
436 // Customize the GroupMask
437 // uint objectGroupMask = ApplyObjectModifyMasks(task.GroupMask, objflags);
438
439 // Customize the EveryoneMask
440 uint objectEveryoneMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags);
441
442
443 // Hack to allow collaboration until Groups and Group Permissions are implemented
444 if ((objectEveryoneMask & (uint)PrimFlags.ObjectMove) != 0)
445 objectEveryoneMask |= (uint)PrimFlags.ObjectModify;
446
447 if (m_bypassPermissions)
448 return objectOwnerMask;
449
450 // Object owners should be able to edit their own content
451 if (user == objectOwner)
452 {
453 return objectOwnerMask;
454 }
455
456 // Users should be able to edit what is over their land.
457 ILandObject parcel = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y);
458 if (parcel != null && parcel.landData.OwnerID == user && m_ParcelOwnerIsGod)
459 return objectOwnerMask;
460
461 // Admin objects should not be editable by the above
462 if (IsAdministrator(objectOwner))
463 return objectEveryoneMask;
464
465 // Estate users should be able to edit anything in the sim
466 if (IsEstateManager(user) && m_RegionOwnerIsGod)
467 return objectOwnerMask;
468
469 // Admin should be able to edit anything in the sim (including admin objects)
470 if (IsAdministrator(user))
471 return objectOwnerMask;
472
473
474 return objectEveryoneMask;
475 }
476
477 private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask)
478 {
479 // We are adding the temporary objectflags to the object's objectflags based on the
480 // permission flag given. These change the F flags on the client.
481
482 if ((setPermissionMask & (uint)PermissionMask.Copy) != 0)
483 {
484 objectFlagsMask |= (uint)PrimFlags.ObjectCopy;
485 }
486
487 if ((setPermissionMask & (uint)PermissionMask.Move) != 0)
488 {
489 objectFlagsMask |= (uint)PrimFlags.ObjectMove;
490 }
491
492 if ((setPermissionMask & (uint)PermissionMask.Modify) != 0)
493 {
494 objectFlagsMask |= (uint)PrimFlags.ObjectModify;
495 }
496
497 if ((setPermissionMask & (uint)PermissionMask.Transfer) != 0)
498 {
499 objectFlagsMask |= (uint)PrimFlags.ObjectTransfer;
500 }
501
502 return objectFlagsMask;
503 }
504
505 /// <summary>
506 /// General permissions checks for any operation involving an object. These supplement more specific checks
507 /// implemented by callers.
508 /// </summary>
509 /// <param name="currentUser"></param>
510 /// <param name="objId"></param>
511 /// <param name="denyOnLocked"></param>
512 /// <returns></returns>
513 protected bool GenericObjectPermission(UUID currentUser, UUID objId, bool denyOnLocked)
514 {
515 // Default: deny
516 bool permission = false;
517 bool locked = false;
518
519 if (!m_scene.Entities.ContainsKey(objId))
520 {
521 return false;
522 }
523
524 // If it's not an object, we cant edit it.
525 if ((!(m_scene.Entities[objId] is SceneObjectGroup)))
526 {
527 return false;
528 }
529
530 SceneObjectGroup group = (SceneObjectGroup)m_scene.Entities[objId];
531
532 UUID objectOwner = group.OwnerID;
533 locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0);
534
535 // People shouldn't be able to do anything with locked objects, except the Administrator
536 // The 'set permissions' runs through a different permission check, so when an object owner
537 // sets an object locked, the only thing that they can do is unlock it.
538 //
539 // Nobody but the object owner can set permissions on an object
540 //
541
542 if (locked && (!IsAdministrator(currentUser)) && denyOnLocked)
543 {
544 return false;
545 }
546
547 // Object owners should be able to edit their own content
548 if (currentUser == objectOwner)
549 {
550 permission = true;
551 }
552 else if (group.IsAttachment)
553 {
554 permission = false;
555 }
556
557 // Users should be able to edit what is over their land.
558 ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y);
559 if ((parcel != null) && (parcel.landData.OwnerID == currentUser))
560 {
561 permission = true;
562 }
563
564 // Estate users should be able to edit anything in the sim
565 if (IsEstateManager(currentUser))
566 {
567 permission = true;
568 }
569
570 // Admin objects should not be editable by the above
571 if (IsAdministrator(objectOwner))
572 {
573 permission = false;
574 }
575
576 // Admin should be able to edit anything in the sim (including admin objects)
577 if (IsAdministrator(currentUser))
578 {
579 permission = true;
580 }
581
582 return permission;
583 }
584
585 #endregion
586
587 #region Generic Permissions
588 protected bool GenericCommunicationPermission(UUID user, UUID target)
589 {
590 // Setting this to true so that cool stuff can happen until we define what determines Generic Communication Permission
591 bool permission = true;
592 string reason = "Only registered users may communicate with another account.";
593
594 // Uhh, we need to finish this before we enable it.. because it's blocking all sorts of goodies and features
595 if (IsAdministrator(user))
596 permission = true;
597
598 if (IsEstateManager(user))
599 permission = true;
600
601 if (!permission)
602 SendPermissionError(user, reason);
603
604 return permission;
605 }
606
607 public bool GenericEstatePermission(UUID user)
608 {
609 // Default: deny
610 bool permission = false;
611
612 // Estate admins should be able to use estate tools
613 if (IsEstateManager(user))
614 permission = true;
615
616 // Administrators always have permission
617 if (IsAdministrator(user))
618 permission = true;
619
620 return permission;
621 }
622
623 protected bool GenericParcelPermission(UUID user, ILandObject parcel)
624 {
625 bool permission = false;
626
627 if (parcel.landData.OwnerID == user)
628 {
629 permission = true;
630 }
631
632 if (parcel.landData.IsGroupOwned)
633 {
634 // TODO: Need to do some extra checks here. Requires group code.
635 }
636
637 if (IsEstateManager(user))
638 {
639 permission = true;
640 }
641
642 if (IsAdministrator(user))
643 {
644 permission = true;
645 }
646
647 return permission;
648 }
649
650 protected bool GenericParcelPermission(UUID user, Vector3 pos)
651 {
652 ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
653 if (parcel == null) return false;
654 return GenericParcelPermission(user, parcel);
655 }
656#endregion
657
658 #region Permission Checks
659 private bool CanAbandonParcel(UUID user, ILandObject parcel, Scene scene)
660 {
661 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
662 if (m_bypassPermissions) return m_bypassPermissionsValue;
663
664 return GenericParcelPermission(user, parcel);
665 }
666
667 private bool CanReclaimParcel(UUID user, ILandObject parcel, Scene scene)
668 {
669 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
670 if (m_bypassPermissions) return m_bypassPermissionsValue;
671
672 return GenericParcelPermission(user, parcel);
673 }
674
675 private bool IsGod(UUID user, Scene scene)
676 {
677 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
678 if (m_bypassPermissions) return m_bypassPermissionsValue;
679
680 return IsAdministrator(user);
681 }
682
683 private bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition)
684 {
685 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
686 if (m_bypassPermissions) return m_bypassPermissionsValue;
687
688 if (!GenericObjectPermission(owner, objectID, true))
689 {
690 //They can't even edit the object
691 return false;
692 }
693
694 SceneObjectPart part = scene.GetSceneObjectPart(objectID);
695 if (part == null)
696 return false;
697
698 if ((part.OwnerMask & PERM_COPY) == 0)
699 return false;
700
701 if ((part.ParentGroup.GetEffectivePermissions() & PERM_COPY) == 0)
702 return false;
703
704 //If they can rez, they can duplicate
705 return CanRezObject(objectCount, owner, objectPosition, scene);
706 }
707
708 private bool CanDeleteObject(UUID objectID, UUID deleter, Scene scene)
709 {
710 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
711 if (m_bypassPermissions) return m_bypassPermissionsValue;
712
713 return GenericObjectPermission(deleter, objectID, false);
714 }
715
716 private bool CanEditObject(UUID objectID, UUID editorID, Scene scene)
717 {
718 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
719 if (m_bypassPermissions) return m_bypassPermissionsValue;
720
721
722 return GenericObjectPermission(editorID, objectID, false);
723 }
724
725 private bool CanEditObjectInventory(UUID objectID, UUID editorID, Scene scene)
726 {
727 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
728 if (m_bypassPermissions) return m_bypassPermissionsValue;
729
730 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
731
732 // If we selected a sub-prim to edit, the objectID won't represent the object, but only a part.
733 // We have to check the permissions of the group, though.
734 if (part.ParentID != 0)
735 {
736 objectID = part.ParentUUID;
737 part = m_scene.GetSceneObjectPart(objectID);
738 }
739
740 // TODO: add group support!
741 //
742 if (part.OwnerID != editorID)
743 return false;
744
745 return GenericObjectPermission(editorID, objectID, false);
746 }
747
748 private bool CanEditParcel(UUID user, ILandObject parcel, Scene scene)
749 {
750 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
751 if (m_bypassPermissions) return m_bypassPermissionsValue;
752
753 return GenericParcelPermission(user, parcel);
754 }
755
756 /// <summary>
757 /// Check whether the specified user can edit the given script
758 /// </summary>
759 /// <param name="script"></param>
760 /// <param name="objectID"></param>
761 /// <param name="user"></param>
762 /// <param name="scene"></param>
763 /// <returns></returns>
764 private bool CanEditScript(UUID script, UUID objectID, UUID user, Scene scene)
765 {
766 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
767 if (m_bypassPermissions) return m_bypassPermissionsValue;
768
769 if (m_allowedScriptEditors == UserSet.Administrators && !IsAdministrator(user))
770 return false;
771
772 // Ordinarily, if you can view it, you can edit it
773 // There is no viewing a no mod script
774 //
775 return CanViewScript(script, objectID, user, scene);
776 }
777
778 /// <summary>
779 /// Check whether the specified user can edit the given notecard
780 /// </summary>
781 /// <param name="notecard"></param>
782 /// <param name="objectID"></param>
783 /// <param name="user"></param>
784 /// <param name="scene"></param>
785 /// <returns></returns>
786 private bool CanEditNotecard(UUID notecard, UUID objectID, UUID user, Scene scene)
787 {
788 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
789 if (m_bypassPermissions) return m_bypassPermissionsValue;
790
791 if (objectID == UUID.Zero) // User inventory
792 {
793 CachedUserInfo userInfo =
794 scene.CommsManager.UserProfileCacheService.GetUserDetails(user);
795
796 if (userInfo == null)
797 {
798 m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for edit notecard check", user);
799 return false;
800 }
801
802 if (userInfo.RootFolder == null)
803 return false;
804
805 InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(notecard);
806 if (assetRequestItem == null) // Library item
807 {
808 assetRequestItem = scene.CommsManager.UserProfileCacheService.LibraryRoot.FindItem(notecard);
809
810 if (assetRequestItem != null) // Implicitly readable
811 return true;
812 }
813
814 // Notecards must be both mod and copy to be saveable
815 // This is because of they're not copy, you can't read
816 // them, and if they're not mod, well, then they're
817 // not mod. Duh.
818 //
819 if ((assetRequestItem.CurrentPermissions &
820 ((uint)PermissionMask.Modify |
821 (uint)PermissionMask.Copy)) !=
822 ((uint)PermissionMask.Modify |
823 (uint)PermissionMask.Copy))
824 return false;
825 }
826 else // Prim inventory
827 {
828 SceneObjectPart part = scene.GetSceneObjectPart(objectID);
829
830 if (part == null)
831 return false;
832
833 if (part.OwnerID != user)
834 return false;
835
836 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
837 return false;
838
839 TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard);
840
841 if (ti == null)
842 return false;
843
844 if (ti.OwnerID != user)
845 return false;
846
847 // Require full perms
848 if ((ti.CurrentPermissions &
849 ((uint)PermissionMask.Modify |
850 (uint)PermissionMask.Copy)) !=
851 ((uint)PermissionMask.Modify |
852 (uint)PermissionMask.Copy))
853 return false;
854 }
855
856 return true;
857 }
858
859 private bool CanInstantMessage(UUID user, UUID target, Scene startScene)
860 {
861 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
862 if (m_bypassPermissions) return m_bypassPermissionsValue;
863
864 // If the sender is an object, check owner instead
865 //
866 SceneObjectPart part = startScene.GetSceneObjectPart(user);
867 if (part != null)
868 user = part.OwnerID;
869
870 return GenericCommunicationPermission(user, target);
871 }
872
873 private bool CanInventoryTransfer(UUID user, UUID target, Scene startScene)
874 {
875 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
876 if (m_bypassPermissions) return m_bypassPermissionsValue;
877
878 return GenericCommunicationPermission(user, target);
879 }
880
881 private bool CanIssueEstateCommand(UUID user, Scene requestFromScene, bool ownerCommand)
882 {
883 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
884 if (m_bypassPermissions) return m_bypassPermissionsValue;
885
886 if (IsAdministrator(user))
887 return true;
888
889 if (m_scene.RegionInfo.EstateSettings.IsEstateOwner(user))
890 return true;
891
892 if (ownerCommand)
893 return false;
894
895 return GenericEstatePermission(user);
896 }
897
898 private bool CanMoveObject(UUID objectID, UUID moverID, Scene scene)
899 {
900 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
901 if (m_bypassPermissions)
902 {
903 SceneObjectPart part = scene.GetSceneObjectPart(objectID);
904 if (part.OwnerID != moverID)
905 {
906 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted)
907 {
908 if (part.ParentGroup.IsAttachment)
909 return false;
910 }
911 }
912 return m_bypassPermissionsValue;
913 }
914
915 bool permission = GenericObjectPermission(moverID, objectID, true);
916 if (!permission)
917 {
918 if (!m_scene.Entities.ContainsKey(objectID))
919 {
920 return false;
921 }
922
923 // The client
924 // may request to edit linked parts, and therefore, it needs
925 // to also check for SceneObjectPart
926
927 // If it's not an object, we cant edit it.
928 if ((!(m_scene.Entities[objectID] is SceneObjectGroup)))
929 {
930 return false;
931 }
932
933
934 SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID];
935
936
937 // UUID taskOwner = null;
938 // Added this because at this point in time it wouldn't be wise for
939 // the administrator object permissions to take effect.
940 // UUID objectOwner = task.OwnerID;
941
942 // Anyone can move
943 if ((task.RootPart.EveryoneMask & PERM_MOVE) != 0)
944 permission = true;
945
946 // Locked
947 if ((task.RootPart.OwnerMask & PERM_LOCKED) == 0)
948 permission = false;
949 }
950 else
951 {
952 bool locked = false;
953 if (!m_scene.Entities.ContainsKey(objectID))
954 {
955 return false;
956 }
957
958 // If it's not an object, we cant edit it.
959 if ((!(m_scene.Entities[objectID] is SceneObjectGroup)))
960 {
961 return false;
962 }
963
964 SceneObjectGroup group = (SceneObjectGroup)m_scene.Entities[objectID];
965
966 UUID objectOwner = group.OwnerID;
967 locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0);
968
969 // This is an exception to the generic object permission.
970 // Administrators who lock their objects should not be able to move them,
971 // however generic object permission should return true.
972 // This keeps locked objects from being affected by random click + drag actions by accident
973 // and allows the administrator to grab or delete a locked object.
974
975 // Administrators and estate managers are still able to click+grab locked objects not
976 // owned by them in the scene
977 // This is by design.
978
979 if (locked && (moverID == objectOwner))
980 return false;
981 }
982 return permission;
983 }
984
985 private bool CanObjectEntry(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene)
986 {
987 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
988 if (m_bypassPermissions) return m_bypassPermissionsValue;
989
990 if ((newPoint.X > 257f || newPoint.X < -1f || newPoint.Y > 257f || newPoint.Y < -1f))
991 {
992 return true;
993 }
994
995 SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID];
996
997 ILandObject land = m_scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y);
998
999 if (!enteringRegion)
1000 {
1001 ILandObject fromland = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y);
1002
1003 if (fromland == land) // Not entering
1004 return true;
1005 }
1006
1007 if (land == null)
1008 {
1009 return false;
1010 }
1011
1012 if ((land.landData.Flags & ((int)Parcel.ParcelFlags.AllowAPrimitiveEntry)) != 0)
1013 {
1014 return true;
1015 }
1016
1017 //TODO: check for group rights
1018
1019 if (!m_scene.Entities.ContainsKey(objectID))
1020 {
1021 return false;
1022 }
1023
1024 // If it's not an object, we cant edit it.
1025 if (!(m_scene.Entities[objectID] is SceneObjectGroup))
1026 {
1027 return false;
1028 }
1029
1030
1031 if (GenericParcelPermission(task.OwnerID, newPoint))
1032 {
1033 return true;
1034 }
1035
1036 //Otherwise, false!
1037 return false;
1038 }
1039
1040 private bool CanReturnObject(UUID objectID, UUID returnerID, Scene scene)
1041 {
1042 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1043 if (m_bypassPermissions) return m_bypassPermissionsValue;
1044
1045 return GenericObjectPermission(returnerID, objectID, false);
1046 }
1047
1048 private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene)
1049 {
1050 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1051 if (m_bypassPermissions) return m_bypassPermissionsValue;
1052
1053 bool permission = false;
1054
1055 ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
1056 if (land == null) return false;
1057
1058 if ((land.landData.Flags & ((int)Parcel.ParcelFlags.CreateObjects)) ==
1059 (int)Parcel.ParcelFlags.CreateObjects)
1060 permission = true;
1061
1062 //TODO: check for group rights
1063
1064 if (IsAdministrator(owner))
1065 {
1066 permission = true;
1067 }
1068
1069 if (GenericParcelPermission(owner, objectPosition))
1070 {
1071 permission = true;
1072 }
1073
1074 return permission;
1075 }
1076
1077 private bool CanRunConsoleCommand(UUID user, Scene requestFromScene)
1078 {
1079 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1080 if (m_bypassPermissions) return m_bypassPermissionsValue;
1081
1082
1083 return IsAdministrator(user);
1084 }
1085
1086 private bool CanRunScript(UUID script, UUID objectID, UUID user, Scene scene)
1087 {
1088 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1089 if (m_bypassPermissions) return m_bypassPermissionsValue;
1090
1091 return true;
1092 }
1093
1094 private bool CanSellParcel(UUID user, ILandObject parcel, Scene scene)
1095 {
1096 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1097 if (m_bypassPermissions) return m_bypassPermissionsValue;
1098
1099 return GenericParcelPermission(user, parcel);
1100 }
1101
1102 private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene)
1103 {
1104 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1105 if (m_bypassPermissions) return m_bypassPermissionsValue;
1106
1107 return GenericObjectPermission(stealer,objectID, false);
1108 }
1109
1110 private bool CanTakeCopyObject(UUID objectID, UUID userID, Scene inScene)
1111 {
1112 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1113 if (m_bypassPermissions) return m_bypassPermissionsValue;
1114
1115 bool permission = GenericObjectPermission(userID, objectID,false);
1116 if (!permission)
1117 {
1118 if (!m_scene.Entities.ContainsKey(objectID))
1119 {
1120 return false;
1121 }
1122
1123 // If it's not an object, we cant edit it.
1124 if (!(m_scene.Entities[objectID] is SceneObjectGroup))
1125 {
1126 return false;
1127 }
1128
1129 SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID];
1130 // UUID taskOwner = null;
1131 // Added this because at this point in time it wouldn't be wise for
1132 // the administrator object permissions to take effect.
1133 // UUID objectOwner = task.OwnerID;
1134
1135 if ((task.RootPart.EveryoneMask & PERM_COPY) != 0)
1136 permission = true;
1137
1138 if ((task.GetEffectivePermissions() & PERM_COPY) == 0)
1139 permission = false;
1140 }
1141 else
1142 {
1143 SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID];
1144
1145 if ((task.GetEffectivePermissions() & PERM_COPY) == 0)
1146 permission = false;
1147 }
1148
1149 return permission;
1150 }
1151
1152 private bool CanTerraformLand(UUID user, Vector3 position, Scene requestFromScene)
1153 {
1154 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1155 if (m_bypassPermissions) return m_bypassPermissionsValue;
1156
1157 // Estate override
1158 if (GenericEstatePermission(user))
1159 return true;
1160
1161 float X = position.X;
1162 float Y = position.Y;
1163
1164 if (X > 255)
1165 X = 255;
1166 if (Y > 255)
1167 Y = 255;
1168 if (X < 0)
1169 X = 0;
1170 if (Y < 0)
1171 Y = 0;
1172
1173 ILandObject parcel = m_scene.LandChannel.GetLandObject(X, Y);
1174 if (parcel == null)
1175 return false;
1176
1177 // Others allowed to terraform?
1178 if ((parcel.landData.Flags & ((int)Parcel.ParcelFlags.AllowTerraform)) != 0)
1179 return true;
1180
1181 // Land owner can terraform too
1182 if (parcel != null && GenericParcelPermission(user, parcel))
1183 return true;
1184
1185 return false;
1186 }
1187
1188 /// <summary>
1189 /// Check whether the specified user can view the given script
1190 /// </summary>
1191 /// <param name="script"></param>
1192 /// <param name="objectID"></param>
1193 /// <param name="user"></param>
1194 /// <param name="scene"></param>
1195 /// <returns></returns>
1196 private bool CanViewScript(UUID script, UUID objectID, UUID user, Scene scene)
1197 {
1198 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1199 if (m_bypassPermissions) return m_bypassPermissionsValue;
1200
1201 if (objectID == UUID.Zero) // User inventory
1202 {
1203 CachedUserInfo userInfo =
1204 scene.CommsManager.UserProfileCacheService.GetUserDetails(user);
1205
1206 if (userInfo == null)
1207 {
1208 m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for administrator check", user);
1209 return false;
1210 }
1211
1212 if (userInfo.RootFolder == null)
1213 return false;
1214
1215 InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(script);
1216 if (assetRequestItem == null) // Library item
1217 {
1218 assetRequestItem = m_scene.CommsManager.UserProfileCacheService.LibraryRoot.FindItem(script);
1219
1220 if (assetRequestItem != null) // Implicitly readable
1221 return true;
1222 }
1223
1224 // SL is rather harebrained here. In SL, a script you
1225 // have mod/copy no trans is readable. This subverts
1226 // permissions, but is used in some products, most
1227 // notably Hippo door plugin and HippoRent 5 networked
1228 // prim counter.
1229 // To enable this broken SL-ism, remove Transfer from
1230 // the below expressions.
1231 // Trying to improve on SL perms by making a script
1232 // readable only if it's really full perms
1233 //
1234 if ((assetRequestItem.CurrentPermissions &
1235 ((uint)PermissionMask.Modify |
1236 (uint)PermissionMask.Copy |
1237 (uint)PermissionMask.Transfer)) !=
1238 ((uint)PermissionMask.Modify |
1239 (uint)PermissionMask.Copy |
1240 (uint)PermissionMask.Transfer))
1241 return false;
1242 }
1243 else // Prim inventory
1244 {
1245 SceneObjectPart part = scene.GetSceneObjectPart(objectID);
1246
1247 if (part == null)
1248 return false;
1249
1250 if (part.OwnerID != user)
1251 return false;
1252
1253 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
1254 return false;
1255
1256 TaskInventoryItem ti = part.Inventory.GetInventoryItem(script);
1257
1258 if (ti == null)
1259 return false;
1260
1261 if (ti.OwnerID != user)
1262 return false;
1263
1264 // Require full perms
1265 if ((ti.CurrentPermissions &
1266 ((uint)PermissionMask.Modify |
1267 (uint)PermissionMask.Copy |
1268 (uint)PermissionMask.Transfer)) !=
1269 ((uint)PermissionMask.Modify |
1270 (uint)PermissionMask.Copy |
1271 (uint)PermissionMask.Transfer))
1272 return false;
1273 }
1274
1275 return true;
1276 }
1277
1278 /// <summary>
1279 /// Check whether the specified user can view the given notecard
1280 /// </summary>
1281 /// <param name="script"></param>
1282 /// <param name="objectID"></param>
1283 /// <param name="user"></param>
1284 /// <param name="scene"></param>
1285 /// <returns></returns>
1286 private bool CanViewNotecard(UUID notecard, UUID objectID, UUID user, Scene scene)
1287 {
1288 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1289 if (m_bypassPermissions) return m_bypassPermissionsValue;
1290
1291 if (objectID == UUID.Zero) // User inventory
1292 {
1293 CachedUserInfo userInfo =
1294 scene.CommsManager.UserProfileCacheService.GetUserDetails(user);
1295
1296 if (userInfo == null)
1297 {
1298 m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for view notecard check", user);
1299 return false;
1300 }
1301
1302 if (userInfo.RootFolder == null)
1303 return false;
1304
1305 InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(notecard);
1306 if (assetRequestItem == null) // Library item
1307 {
1308 assetRequestItem = m_scene.CommsManager.UserProfileCacheService.LibraryRoot.FindItem(notecard);
1309
1310 if (assetRequestItem != null) // Implicitly readable
1311 return true;
1312 }
1313
1314 // Notecards are always readable unless no copy
1315 //
1316 if ((assetRequestItem.CurrentPermissions &
1317 (uint)PermissionMask.Copy) !=
1318 (uint)PermissionMask.Copy)
1319 return false;
1320 }
1321 else // Prim inventory
1322 {
1323 SceneObjectPart part = scene.GetSceneObjectPart(objectID);
1324
1325 if (part == null)
1326 return false;
1327
1328 if (part.OwnerID != user)
1329 return false;
1330
1331 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
1332 return false;
1333
1334 TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard);
1335
1336 if (ti == null)
1337 return false;
1338
1339 if (ti.OwnerID != user)
1340 return false;
1341
1342 // Notecards are always readable unless no copy
1343 //
1344 if ((ti.CurrentPermissions &
1345 (uint)PermissionMask.Copy) !=
1346 (uint)PermissionMask.Copy)
1347 return false;
1348 }
1349
1350 return true;
1351 }
1352
1353 #endregion
1354
1355 private bool CanLinkObject(UUID userID, UUID objectID)
1356 {
1357 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1358 if (m_bypassPermissions) return m_bypassPermissionsValue;
1359
1360 return true;
1361 }
1362
1363 private bool CanDelinkObject(UUID userID, UUID objectID)
1364 {
1365 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1366 if (m_bypassPermissions) return m_bypassPermissionsValue;
1367
1368 return true;
1369 }
1370
1371 private bool CanBuyLand(UUID userID, ILandObject parcel, Scene scene)
1372 {
1373 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1374 if (m_bypassPermissions) return m_bypassPermissionsValue;
1375
1376 return true;
1377 }
1378
1379 private bool CanCopyObjectInventory(UUID itemID, UUID objectID, UUID userID)
1380 {
1381 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1382 if (m_bypassPermissions) return m_bypassPermissionsValue;
1383
1384 return true;
1385 }
1386
1387 private bool CanDeleteObjectInventory(UUID itemID, UUID objectID, UUID userID)
1388 {
1389 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1390 if (m_bypassPermissions) return m_bypassPermissionsValue;
1391
1392 return true;
1393 }
1394
1395 /// <summary>
1396 /// Check whether the specified user is allowed to directly create the given inventory type in a prim's
1397 /// inventory (e.g. the New Script button in the 1.21 Linden Lab client).
1398 /// </summary>
1399 /// <param name="invType"></param>
1400 /// <param name="objectID"></param>
1401 /// <param name="userID"></param>
1402 /// <returns></returns>
1403 private bool CanCreateObjectInventory(int invType, UUID objectID, UUID userID)
1404 {
1405 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1406 if (m_bypassPermissions) return m_bypassPermissionsValue;
1407
1408 if ((int)InventoryType.LSL == invType)
1409 if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID))
1410 return false;
1411
1412 return true;
1413 }
1414
1415 /// <summary>
1416 /// Check whether the specified user is allowed to create the given inventory type in their inventory.
1417 /// </summary>
1418 /// <param name="invType"></param>
1419 /// <param name="userID"></param>
1420 /// <returns></returns>
1421 private bool CanCreateUserInventory(int invType, UUID userID)
1422 {
1423 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1424 if (m_bypassPermissions) return m_bypassPermissionsValue;
1425
1426 if ((int)InventoryType.LSL == invType)
1427 if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID))
1428 return false;
1429
1430 return true;
1431 }
1432
1433 /// <summary>
1434 /// Check whether the specified user is allowed to copy the given inventory type in their inventory.
1435 /// </summary>
1436 /// <param name="itemID"></param>
1437 /// <param name="userID"></param>
1438 /// <returns></returns>
1439 private bool CanCopyUserInventory(UUID itemID, UUID userID)
1440 {
1441 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1442 if (m_bypassPermissions) return m_bypassPermissionsValue;
1443
1444 return true;
1445 }
1446
1447 /// <summary>
1448 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory.
1449 /// </summary>
1450 /// <param name="itemID"></param>
1451 /// <param name="userID"></param>
1452 /// <returns></returns>
1453 private bool CanEditUserInventory(UUID itemID, UUID userID)
1454 {
1455 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1456 if (m_bypassPermissions) return m_bypassPermissionsValue;
1457
1458 return true;
1459 }
1460
1461 /// <summary>
1462 /// Check whether the specified user is allowed to delete the given inventory item from their own inventory.
1463 /// </summary>
1464 /// <param name="itemID"></param>
1465 /// <param name="userID"></param>
1466 /// <returns></returns>
1467 private bool CanDeleteUserInventory(UUID itemID, UUID userID)
1468 {
1469 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1470 if (m_bypassPermissions) return m_bypassPermissionsValue;
1471
1472 return true;
1473 }
1474
1475 private bool CanTeleport(UUID userID)
1476 {
1477 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1478 if (m_bypassPermissions) return m_bypassPermissionsValue;
1479
1480 return true;
1481 }
1482
1483 private bool CanResetScript(UUID prim, UUID script, UUID agentID, Scene scene)
1484 {
1485 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1486 if (m_bypassPermissions) return m_bypassPermissionsValue;
1487
1488 SceneObjectPart part = m_scene.GetSceneObjectPart(prim);
1489
1490 // If we selected a sub-prim to reset, prim won't represent the object, but only a part.
1491 // We have to check the permissions of the object, though.
1492 if (part.ParentID != 0) prim = part.ParentUUID;
1493
1494 // You can reset the scripts in any object you can edit
1495 return GenericObjectPermission(agentID, prim, false);
1496 }
1497 }
1498}
diff --git a/OpenSim/Region/Environment/Modules/World/Serialiser/IFileSerialiser.cs b/OpenSim/Region/Environment/Modules/World/Serialiser/IFileSerialiser.cs
deleted file mode 100644
index afad3cf..0000000
--- a/OpenSim/Region/Environment/Modules/World/Serialiser/IFileSerialiser.cs
+++ /dev/null
@@ -1,36 +0,0 @@
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 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 */
27
28using OpenSim.Region.Framework.Scenes;
29
30namespace OpenSim.Region.Environment.Modules.World.Serialiser
31{
32 internal interface IFileSerialiser
33 {
34 string WriteToFile(Scene scene, string dir);
35 }
36} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseObjects.cs b/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseObjects.cs
deleted file mode 100644
index 8b3f2ce..0000000
--- a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseObjects.cs
+++ /dev/null
@@ -1,125 +0,0 @@
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 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 */
27
28using System.Collections.Generic;
29using System.IO;
30using System.IO.Compression;
31using System.Text;
32using System.Xml;
33using OpenSim.Region.Framework.Scenes;
34
35namespace OpenSim.Region.Environment.Modules.World.Serialiser
36{
37 internal class SerialiseObjects : IFileSerialiser
38 {
39 #region IFileSerialiser Members
40
41 public string WriteToFile(Scene scene, string dir)
42 {
43 string targetFileName = dir + "objects.xml";
44
45 SaveSerialisedToFile(targetFileName, scene);
46
47 return "objects.xml";
48 }
49
50 #endregion
51
52 public void SaveSerialisedToFile(string fileName, Scene scene)
53 {
54 string xmlstream = GetObjectXml(scene);
55
56 MemoryStream stream = ReformatXmlString(xmlstream);
57
58 stream.Seek(0, SeekOrigin.Begin);
59 CreateXmlFile(stream, fileName);
60
61 stream.Seek(0, SeekOrigin.Begin);
62 CreateCompressedXmlFile(stream, fileName);
63 }
64
65 private static MemoryStream ReformatXmlString(string xmlstream)
66 {
67 MemoryStream stream = new MemoryStream();
68 XmlTextWriter formatter = new XmlTextWriter(stream, Encoding.UTF8);
69 XmlDocument doc = new XmlDocument();
70
71 doc.LoadXml(xmlstream);
72 formatter.Formatting = Formatting.Indented;
73 doc.WriteContentTo(formatter);
74 formatter.Flush();
75 return stream;
76 }
77
78 private static string GetObjectXml(Scene scene)
79 {
80 string xmlstream = "<scene>";
81
82 List<EntityBase> EntityList = scene.GetEntities();
83 List<string> EntityXml = new List<string>();
84
85 foreach (EntityBase ent in EntityList)
86 {
87 if (ent is SceneObjectGroup)
88 {
89 EntityXml.Add(((SceneObjectGroup) ent).ToXmlString2());
90 }
91 }
92 EntityXml.Sort();
93
94 foreach (string xml in EntityXml)
95 xmlstream += xml;
96
97 xmlstream += "</scene>";
98 return xmlstream;
99 }
100
101 private static void CreateXmlFile(MemoryStream xmlStream, string fileName)
102 {
103 FileStream objectsFile = new FileStream(fileName, FileMode.Create);
104
105 xmlStream.WriteTo(objectsFile);
106 objectsFile.Flush();
107 objectsFile.Close();
108 }
109
110 private static void CreateCompressedXmlFile(MemoryStream xmlStream, string fileName)
111 {
112 #region GZip Compressed Version
113
114 FileStream objectsFileCompressed = new FileStream(fileName + ".gzs", FileMode.Create);
115 MemoryStream gzipMSStream = new MemoryStream();
116 GZipStream gzipStream = new GZipStream(gzipMSStream, CompressionMode.Compress);
117 xmlStream.WriteTo(gzipStream);
118 gzipMSStream.WriteTo(objectsFileCompressed);
119 objectsFileCompressed.Flush();
120 objectsFileCompressed.Close();
121
122 #endregion
123 }
124 }
125}
diff --git a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseTerrain.cs b/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseTerrain.cs
deleted file mode 100644
index d0ce3d8..0000000
--- a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseTerrain.cs
+++ /dev/null
@@ -1,53 +0,0 @@
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 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 */
27
28using OpenSim.Region.Environment.Modules.World.Terrain;
29using OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Environment.Modules.World.Serialiser
33{
34 internal class SerialiseTerrain : IFileSerialiser
35 {
36 #region IFileSerialiser Members
37
38 public string WriteToFile(Scene scene, string dir)
39 {
40 ITerrainLoader fileSystemExporter = new RAW32();
41 string targetFileName = dir + "heightmap.r32";
42
43 lock (scene.Heightmap)
44 {
45 fileSystemExporter.SaveFile(targetFileName, scene.Heightmap);
46 }
47
48 return "heightmap.r32";
49 }
50
51 #endregion
52 }
53} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiserModule.cs b/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiserModule.cs
deleted file mode 100644
index 0e7873c..0000000
--- a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiserModule.cs
+++ /dev/null
@@ -1,226 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using OpenMetaverse;
32using Nini.Config;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Region.Environment.Modules.Framework.InterfaceCommander;
36
37namespace OpenSim.Region.Environment.Modules.World.Serialiser
38{
39 public class SerialiserModule : IRegionModule, IRegionSerialiserModule
40 {
41 private Commander m_commander = new Commander("export");
42 private List<Scene> m_regions = new List<Scene>();
43 private string m_savedir = "exports" + "/";
44 private List<IFileSerialiser> m_serialisers = new List<IFileSerialiser>();
45
46 #region IRegionModule Members
47
48 public void Initialise(Scene scene, IConfigSource source)
49 {
50 scene.RegisterModuleCommander(m_commander);
51 scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
52 scene.RegisterModuleInterface<IRegionSerialiserModule>(this);
53
54 lock (m_regions)
55 {
56 m_regions.Add(scene);
57 }
58 }
59
60 public void PostInitialise()
61 {
62 lock (m_serialisers)
63 {
64 m_serialisers.Add(new SerialiseTerrain());
65 m_serialisers.Add(new SerialiseObjects());
66 }
67
68 LoadCommanderCommands();
69 }
70
71 public void Close()
72 {
73 m_regions.Clear();
74 }
75
76 public string Name
77 {
78 get { return "ExportSerialisationModule"; }
79 }
80
81 public bool IsSharedModule
82 {
83 get { return true; }
84 }
85
86 #endregion
87
88 #region IRegionSerialiser Members
89
90 public void LoadPrimsFromXml(Scene scene, string fileName, bool newIDS, Vector3 loadOffset)
91 {
92 SceneXmlLoader.LoadPrimsFromXml(scene, fileName, newIDS, loadOffset);
93 }
94
95 public void SavePrimsToXml(Scene scene, string fileName)
96 {
97 SceneXmlLoader.SavePrimsToXml(scene, fileName);
98 }
99
100 public void LoadPrimsFromXml2(Scene scene, string fileName)
101 {
102 SceneXmlLoader.LoadPrimsFromXml2(scene, fileName);
103 }
104
105 public void LoadPrimsFromXml2(Scene scene, TextReader reader, bool startScripts)
106 {
107 SceneXmlLoader.LoadPrimsFromXml2(scene, reader, startScripts);
108 }
109
110 public void SavePrimsToXml2(Scene scene, string fileName)
111 {
112 SceneXmlLoader.SavePrimsToXml2(scene, fileName);
113 }
114
115 public void SavePrimsToXml2(Scene scene, TextWriter stream, Vector3 min, Vector3 max)
116 {
117 SceneXmlLoader.SavePrimsToXml2(scene, stream, min, max);
118 }
119
120 public void SaveNamedPrimsToXml2(Scene scene, string primName, string fileName)
121 {
122 SceneXmlLoader.SaveNamedPrimsToXml2(scene, primName, fileName);
123 }
124
125 public SceneObjectGroup DeserializeGroupFromXml2(string xmlString)
126 {
127 return SceneXmlLoader.DeserializeGroupFromXml2(xmlString);
128 }
129
130 public string SaveGroupToXml2(SceneObjectGroup grp)
131 {
132 return SceneXmlLoader.SaveGroupToXml2(grp);
133 }
134
135 public void SavePrimListToXml2(List<EntityBase> entityList, string fileName)
136 {
137 SceneXmlLoader.SavePrimListToXml2(entityList, fileName);
138 }
139
140 public void SavePrimListToXml2(List<EntityBase> entityList, TextWriter stream, Vector3 min, Vector3 max)
141 {
142 SceneXmlLoader.SavePrimListToXml2(entityList, stream, min, max);
143 }
144
145 public List<string> SerialiseRegion(Scene scene, string saveDir)
146 {
147 List<string> results = new List<string>();
148
149 if (!Directory.Exists(saveDir))
150 {
151 Directory.CreateDirectory(saveDir);
152 }
153
154 lock (m_serialisers)
155 {
156 foreach (IFileSerialiser serialiser in m_serialisers)
157 {
158 results.Add(serialiser.WriteToFile(scene, saveDir));
159 }
160 }
161
162 TextWriter regionInfoWriter = new StreamWriter(saveDir + "README.TXT");
163 regionInfoWriter.WriteLine("Region Name: " + scene.RegionInfo.RegionName);
164 regionInfoWriter.WriteLine("Region ID: " + scene.RegionInfo.RegionID.ToString());
165 regionInfoWriter.WriteLine("Backup Time: UTC " + DateTime.UtcNow.ToString());
166 regionInfoWriter.WriteLine("Serialise Version: 0.1");
167 regionInfoWriter.Close();
168
169 TextWriter manifestWriter = new StreamWriter(saveDir + "region.manifest");
170 foreach (string line in results)
171 {
172 manifestWriter.WriteLine(line);
173 }
174 manifestWriter.Close();
175
176 return results;
177 }
178
179 #endregion
180
181 private void EventManager_OnPluginConsole(string[] args)
182 {
183 if (args[0] == "export")
184 {
185 string[] tmpArgs = new string[args.Length - 2];
186 int i = 0;
187 for (i = 2; i < args.Length; i++)
188 tmpArgs[i - 2] = args[i];
189
190 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
191 }
192 }
193
194 private void InterfaceSaveRegion(Object[] args)
195 {
196 foreach (Scene region in m_regions)
197 {
198 if (region.RegionInfo.RegionName == (string) args[0])
199 {
200 // List<string> results = SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/");
201 SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/");
202 }
203 }
204 }
205
206 private void InterfaceSaveAllRegions(Object[] args)
207 {
208 foreach (Scene region in m_regions)
209 {
210 // List<string> results = SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/");
211 SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/");
212 }
213 }
214
215 private void LoadCommanderCommands()
216 {
217 Command serialiseSceneCommand = new Command("save", CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceSaveRegion, "Saves the named region into the exports directory.");
218 serialiseSceneCommand.AddArgument("region-name", "The name of the region you wish to export", "String");
219
220 Command serialiseAllScenesCommand = new Command("save-all",CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceSaveAllRegions, "Saves all regions into the exports directory.");
221
222 m_commander.RegisterCommand("save", serialiseSceneCommand);
223 m_commander.RegisterCommand("save-all", serialiseAllScenesCommand);
224 }
225 }
226}
diff --git a/OpenSim/Region/Environment/Modules/World/Sound/SoundModule.cs b/OpenSim/Region/Environment/Modules/World/Sound/SoundModule.cs
deleted file mode 100644
index 1713797..0000000
--- a/OpenSim/Region/Environment/Modules/World/Sound/SoundModule.cs
+++ /dev/null
@@ -1,97 +0,0 @@
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 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 */
27
28using System;
29using System.Reflection;
30using Nini.Config;
31using log4net;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36
37namespace OpenSim.Region.Environment.World.Sound
38{
39 public class SoundModule : IRegionModule, ISoundModule
40 {
41 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 protected Scene m_scene;
44
45 public void Initialise(Scene scene, IConfigSource source)
46 {
47 m_scene = scene;
48
49 m_scene.EventManager.OnNewClient += OnNewClient;
50
51 m_scene.RegisterModuleInterface<ISoundModule>(this);
52 }
53
54 public void PostInitialise() {}
55 public void Close() {}
56 public string Name { get { return "Sound Module"; } }
57 public bool IsSharedModule { get { return false; } }
58
59 private void OnNewClient(IClientAPI client)
60 {
61 client.OnSoundTrigger += TriggerSound;
62 }
63
64 public virtual void PlayAttachedSound(
65 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags)
66 {
67 foreach (ScenePresence p in m_scene.GetAvatars())
68 {
69 double dis = Util.GetDistanceTo(p.AbsolutePosition, position);
70 if (dis > 100.0) // Max audio distance
71 continue;
72
73 // Scale by distance
74 gain = (float)((double)gain*((100.0 - dis) / 100.0));
75
76 p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags);
77 }
78 }
79
80 public virtual void TriggerSound(
81 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle)
82 {
83 foreach (ScenePresence p in m_scene.GetAvatars())
84 {
85 double dis = Util.GetDistanceTo(p.AbsolutePosition, position);
86 if (dis > 100.0) // Max audio distance
87 continue;
88
89 // Scale by distance
90 gain = (float)((double)gain*((100.0 - dis) / 100.0));
91
92 p.ControllingClient.SendTriggeredSound(
93 soundId, ownerID, objectID, parentID, handle, position, (float)gain);
94 }
95 }
96 }
97}
diff --git a/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs b/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs
deleted file mode 100644
index ee96d58..0000000
--- a/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs
+++ /dev/null
@@ -1,434 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using Nini.Config;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes;
35
36namespace OpenSim.Region.Environment.Modules
37{
38 public class SunModule : IRegionModule
39 {
40
41 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
42
43 private const double SeasonalTilt = 0.03 * Math.PI; // A daily shift of approximately 1.7188 degrees
44 private const double AverageTilt = -0.25 * Math.PI; // A 45 degree tilt
45 private const double SunCycle = 2.0D * Math.PI; // A perfect circle measured in radians
46 private const double SeasonalCycle = 2.0D * Math.PI; // Ditto
47
48 //
49 // Per Region Values
50 //
51
52 private bool ready = false;
53
54 // Configurable values
55 private string m_mode = "SL";
56 private int m_frame_mod = 0;
57 private double m_day_length = 0;
58 private int m_year_length = 0;
59 private double m_day_night = 0;
60 // private double m_longitude = 0;
61 // private double m_latitude = 0;
62 // Configurable defaults Defaults close to SL
63 private string d_mode = "SL";
64 private int d_frame_mod = 100; // Every 10 seconds (actually less)
65 private double d_day_length = 4; // A VW day is 4 RW hours long
66 private int d_year_length = 60; // There are 60 VW days in a VW year
67 private double d_day_night = 0.45; // axis offset: ratio of light-to-dark, approx 1:3
68 // private double d_longitude = -73.53;
69 // private double d_latitude = 41.29;
70
71 // Frame counter
72 private uint m_frame = 0;
73
74 // Cached Scene reference
75 private Scene m_scene = null;
76
77 // Calculated Once in the lifetime of a region
78 private long TicksToEpoch; // Elapsed time for 1/1/1970
79 private uint SecondsPerSunCycle; // Length of a virtual day in RW seconds
80 private uint SecondsPerYear; // Length of a virtual year in RW seconds
81 private double SunSpeed; // Rate of passage in radians/second
82 private double SeasonSpeed; // Rate of change for seasonal effects
83 // private double HoursToRadians; // Rate of change for seasonal effects
84 private long TicksOffset = 0; // seconds offset from UTC
85 // Calculated every update
86 private float OrbitalPosition; // Orbital placement at a point in time
87 private double HorizonShift; // Axis offset to skew day and night
88 private double TotalDistanceTravelled; // Distance since beginning of time (in radians)
89 private double SeasonalOffset; // Seaonal variation of tilt
90 private float Magnitude; // Normal tilt
91 // private double VWTimeRatio; // VW time as a ratio of real time
92
93 // Working values
94 private Vector3 Position = Vector3.Zero;
95 private Vector3 Velocity = Vector3.Zero;
96 private Quaternion Tilt = new Quaternion(1.0f, 0.0f, 0.0f, 0.0f);
97
98 private long LindenHourOffset = 0;
99 private bool sunFixed = false;
100
101 private Dictionary<UUID, ulong> m_rootAgents = new Dictionary<UUID, ulong>();
102
103 // Current time in elapsed seconds since Jan 1st 1970
104 private ulong CurrentTime
105 {
106 get {
107 return (ulong)(((System.DateTime.Now.Ticks) - TicksToEpoch + TicksOffset + LindenHourOffset)/10000000);
108 }
109 }
110
111 private float GetLindenEstateHourFromCurrentTime()
112 {
113 float ticksleftover = ((float)CurrentTime) % ((float)SecondsPerSunCycle);
114
115 float hour = (24 * (ticksleftover / SecondsPerSunCycle)) + 6;
116
117 return hour;
118 }
119
120 private void SetTimeByLindenHour(float LindenHour)
121 {
122 // Linden hour is 24 hours with a 6 hour offset. 6-30
123
124 if (LindenHour - 6 == 0)
125 {
126 LindenHourOffset = 0;
127 return;
128 }
129
130 // Remove LindenHourOffset to calculate it from LocalTime
131 float ticksleftover = ((float)(((long)(CurrentTime * 10000000) - (long)LindenHourOffset)/ 10000000) % ((float)SecondsPerSunCycle));
132 float hour = (24 * (ticksleftover / SecondsPerSunCycle));
133
134 float offsethours = 0;
135
136 if (LindenHour - 6 > hour)
137 {
138 offsethours = hour + ((LindenHour-6) - hour);
139 }
140 else
141 {
142 offsethours = hour - (hour - (LindenHour - 6));
143 }
144 //m_log.Debug("[OFFSET]: " + hour + " - " + LindenHour + " - " + offsethours.ToString());
145
146 LindenHourOffset = (long)((float)offsethours * (36000000000/m_day_length));
147 m_log.Debug("[SUN]: Directive from the Estate Tools to set the sun phase to LindenHour " + GetLindenEstateHourFromCurrentTime().ToString());
148 }
149
150 // Called immediately after the module is loaded for a given region
151 // i.e. Immediately after instance creation.
152 public void Initialise(Scene scene, IConfigSource config)
153 {
154 m_scene = scene;
155
156 m_frame = 0;
157
158 TimeZone local = TimeZone.CurrentTimeZone;
159 TicksOffset = local.GetUtcOffset(local.ToLocalTime(DateTime.Now)).Ticks;
160 m_log.Debug("[SUN]: localtime offset is " + TicksOffset);
161
162 // Align ticks with Second Life
163
164 TicksToEpoch = new System.DateTime(1970,1,1).Ticks;
165
166 // Just in case they don't have the stanzas
167 try
168 {
169 // Mode: determines how the sun is handled
170 m_mode = config.Configs["Sun"].GetString("mode", d_mode);
171 // Mode: determines how the sun is handled
172 // m_latitude = config.Configs["Sun"].GetDouble("latitude", d_latitude);
173 // Mode: determines how the sun is handled
174 // m_longitude = config.Configs["Sun"].GetDouble("longitude", d_longitude);
175 // Year length in days
176 m_year_length = config.Configs["Sun"].GetInt("year_length", d_year_length);
177 // Day length in decimal hours
178 m_day_length = config.Configs["Sun"].GetDouble("day_length", d_day_length);
179 // Day to Night Ratio
180 m_day_night = config.Configs["Sun"].GetDouble("day_night_offset", d_day_night);
181 // Update frequency in frames
182 m_frame_mod = config.Configs["Sun"].GetInt("update_interval", d_frame_mod);
183 }
184 catch (Exception e)
185 {
186 m_log.Debug("[SUN]: Configuration access failed, using defaults. Reason: "+e.Message);
187 m_mode = d_mode;
188 m_year_length = d_year_length;
189 m_day_length = d_day_length;
190 m_day_night = d_day_night;
191 m_frame_mod = d_frame_mod;
192 // m_latitude = d_latitude;
193 // m_longitude = d_longitude;
194 }
195
196 switch (m_mode)
197 {
198 case "T1":
199 default:
200 case "SL":
201 // Time taken to complete a cycle (day and season)
202
203 SecondsPerSunCycle = (uint) (m_day_length * 60 * 60);
204 SecondsPerYear = (uint) (SecondsPerSunCycle*m_year_length);
205
206 // Ration of real-to-virtual time
207
208 // VWTimeRatio = 24/m_day_length;
209
210 // Speed of rotation needed to complete a cycle in the
211 // designated period (day and season)
212
213 SunSpeed = SunCycle/SecondsPerSunCycle;
214 SeasonSpeed = SeasonalCycle/SecondsPerYear;
215
216 // Horizon translation
217
218 HorizonShift = m_day_night; // Z axis translation
219 // HoursToRadians = (SunCycle/24)*VWTimeRatio;
220
221 // Insert our event handling hooks
222
223 scene.EventManager.OnFrame += SunUpdate;
224 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
225 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
226 scene.EventManager.OnClientClosed += ClientLoggedOut;
227 scene.EventManager.OnEstateToolsTimeUpdate += EstateToolsTimeUpdate;
228 scene.EventManager.OnGetSunLindenHour += GetLindenEstateHourFromCurrentTime;
229
230 ready = true;
231
232 m_log.Debug("[SUN]: Mode is "+m_mode);
233 m_log.Debug("[SUN]: Initialization completed. Day is "+SecondsPerSunCycle+" seconds, and year is "+m_year_length+" days");
234 m_log.Debug("[SUN]: Axis offset is "+m_day_night);
235 m_log.Debug("[SUN]: Positional data updated every "+m_frame_mod+" frames");
236
237 break;
238 }
239 }
240
241 public void PostInitialise()
242 {
243 }
244
245 public void Close()
246 {
247 ready = false;
248
249 // Remove our hooks
250 m_scene.EventManager.OnFrame -= SunUpdate;
251 m_scene.EventManager.OnMakeChildAgent -= MakeChildAgent;
252 m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel;
253 m_scene.EventManager.OnClientClosed -= ClientLoggedOut;
254 m_scene.EventManager.OnEstateToolsTimeUpdate -= EstateToolsTimeUpdate;
255 m_scene.EventManager.OnGetSunLindenHour -= GetLindenEstateHourFromCurrentTime;
256 }
257
258 public string Name
259 {
260 get { return "SunModule"; }
261 }
262
263 public bool IsSharedModule
264 {
265 get { return false; }
266 }
267
268 public void SunToClient(IClientAPI client)
269 {
270 if (m_mode != "T1")
271 {
272 if (ready)
273 {
274 if (!sunFixed)
275 GenSunPos(); // Generate shared values once
276 client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
277 }
278 }
279 }
280
281 public void SunUpdate()
282 {
283 if (((m_frame++%m_frame_mod) != 0) || !ready || sunFixed)
284 {
285 return;
286 }
287
288 GenSunPos(); // Generate shared values once
289
290 List<ScenePresence> avatars = m_scene.GetAvatars();
291 foreach (ScenePresence avatar in avatars)
292 {
293 if (!avatar.IsChildAgent)
294 avatar.ControllingClient.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
295 }
296
297 // set estate settings for region access to sun position
298 m_scene.RegionInfo.RegionSettings.SunVector = Position;
299 //m_scene.RegionInfo.EstateSettings.sunHour = GetLindenEstateHourFromCurrentTime();
300 }
301
302 public void ForceSunUpdateToAllClients()
303 {
304 GenSunPos(); // Generate shared values once
305
306 List<ScenePresence> avatars = m_scene.GetAvatars();
307 foreach (ScenePresence avatar in avatars)
308 {
309 if (!avatar.IsChildAgent)
310 avatar.ControllingClient.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
311 }
312
313 // set estate settings for region access to sun position
314 m_scene.RegionInfo.RegionSettings.SunVector = Position;
315 m_scene.RegionInfo.RegionSettings.SunPosition = GetLindenEstateHourFromCurrentTime();
316 }
317
318 /// <summary>
319 /// Calculate the sun's orbital position and its velocity.
320 /// </summary>
321 private void GenSunPos()
322 {
323 TotalDistanceTravelled = SunSpeed * CurrentTime; // distance measured in radians
324 OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); // position measured in radians
325
326 // TotalDistanceTravelled += HoursToRadians-(0.25*Math.PI)*Math.Cos(HoursToRadians)-OrbitalPosition;
327 // OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle);
328
329 SeasonalOffset = SeasonSpeed * CurrentTime; // Present season determined as total radians travelled around season cycle
330
331 Tilt.W = (float) (AverageTilt + (SeasonalTilt*Math.Sin(SeasonalOffset))); // Calculate seasonal orbital N/S tilt
332
333 // m_log.Debug("[SUN] Total distance travelled = "+TotalDistanceTravelled+", present position = "+OrbitalPosition+".");
334 // m_log.Debug("[SUN] Total seasonal progress = "+SeasonalOffset+", present tilt = "+Tilt.W+".");
335
336 // The sun rotates about the Z axis
337
338 Position.X = (float) Math.Cos(-TotalDistanceTravelled);
339 Position.Y = (float) Math.Sin(-TotalDistanceTravelled);
340 Position.Z = 0;
341
342 // For interest we rotate it slightly about the X access.
343 // Celestial tilt is a value that ranges .025
344
345 Position *= Tilt;
346
347 // Finally we shift the axis so that more of the
348 // circle is above the horizon than below. This
349 // makes the nights shorter than the days.
350
351 Position.Z = Position.Z + (float) HorizonShift;
352 Position = Vector3.Normalize(Position);
353
354 // m_log.Debug("[SUN] Position("+Position.X+","+Position.Y+","+Position.Z+")");
355
356 Velocity.X = 0;
357 Velocity.Y = 0;
358 Velocity.Z = (float) SunSpeed;
359
360 // Correct angular velocity to reflect the seasonal rotation
361
362 Magnitude = Position.Length();
363 if (sunFixed)
364 {
365 Velocity.X = 0;
366 Velocity.Y = 0;
367 Velocity.Z = 0;
368 return;
369 }
370
371 Velocity = (Velocity * Tilt) * (1.0f / Magnitude);
372
373 // m_log.Debug("[SUN] Velocity("+Velocity.X+","+Velocity.Y+","+Velocity.Z+")");
374 }
375
376 private void ClientLoggedOut(UUID AgentId)
377 {
378 lock (m_rootAgents)
379 {
380 if (m_rootAgents.ContainsKey(AgentId))
381 {
382 m_rootAgents.Remove(AgentId);
383 }
384 }
385 }
386
387 private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID)
388 {
389 lock (m_rootAgents)
390 {
391 if (m_rootAgents.ContainsKey(avatar.UUID))
392 {
393 m_rootAgents[avatar.UUID] = avatar.RegionHandle;
394 }
395 else
396 {
397 m_rootAgents.Add(avatar.UUID, avatar.RegionHandle);
398 SunToClient(avatar.ControllingClient);
399 }
400 }
401 //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString());
402 }
403
404 private void MakeChildAgent(ScenePresence avatar)
405 {
406 lock (m_rootAgents)
407 {
408 if (m_rootAgents.ContainsKey(avatar.UUID))
409 {
410 if (m_rootAgents[avatar.UUID] == avatar.RegionHandle)
411 {
412 m_rootAgents.Remove(avatar.UUID);
413 }
414 }
415 }
416 }
417
418 public void EstateToolsTimeUpdate(ulong regionHandle, bool FixedTime, bool useEstateTime, float LindenHour)
419 {
420 if (m_scene.RegionInfo.RegionHandle == regionHandle)
421 {
422 SetTimeByLindenHour(LindenHour);
423
424 //if (useEstateTime)
425 //LindenHourOffset = 0;
426
427 ForceSunUpdateToAllClients();
428 sunFixed = FixedTime;
429 if (sunFixed)
430 GenSunPos();
431 }
432 }
433 }
434}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/Effects/CookieCutter.cs b/OpenSim/Region/Environment/Modules/World/Terrain/Effects/CookieCutter.cs
deleted file mode 100644
index 83246fb..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/Effects/CookieCutter.cs
+++ /dev/null
@@ -1,125 +0,0 @@
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 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 System;
28using OpenSim.Region.Framework.Interfaces;
29using OpenSim.Region.Framework.Scenes;
30using OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes;
31
32namespace OpenSim.Region.Environment.Modules.World.Terrain.Effects
33{
34 internal class CookieCutter : ITerrainEffect
35 {
36 #region ITerrainEffect Members
37
38 public void RunEffect(ITerrainChannel map)
39 {
40 ITerrainPaintableEffect eroder = new WeatherSphere();
41
42 bool[,] cliffMask = new bool[map.Width,map.Height];
43 bool[,] channelMask = new bool[map.Width,map.Height];
44 bool[,] smoothMask = new bool[map.Width,map.Height];
45 bool[,] allowMask = new bool[map.Width,map.Height];
46
47 Console.WriteLine("S1");
48
49 // Step one, generate rough mask
50 int x, y;
51 for (x = 0; x < map.Width; x++)
52 {
53 for (y = 0; y < map.Height; y++)
54 {
55 Console.Write(".");
56 smoothMask[x, y] = true;
57 allowMask[x,y] = true;
58
59 // Start underwater
60 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 5;
61 // Add a little height. (terrain should now be above water, mostly.)
62 map[x, y] += 20;
63
64 const int channelsX = 4;
65 int channelWidth = (map.Width / channelsX / 4);
66 const int channelsY = 4;
67 int channelHeight = (map.Height / channelsY / 4);
68
69 SetLowerChannel(map, cliffMask, channelMask, x, y, channelsX, channelWidth, map.Width, x);
70 SetLowerChannel(map, cliffMask, channelMask, x, y, channelsY, channelHeight, map.Height, y);
71 }
72 }
73
74 Console.WriteLine("S2");
75 //smooth.FloodEffect(map, smoothMask, 4.0);
76
77 Console.WriteLine("S3");
78 for (x = 0; x < map.Width; x++)
79 {
80 for (y = 0; y < map.Height; y++)
81 {
82 if (cliffMask[x, y])
83 eroder.PaintEffect(map, allowMask, x, y, -1, 4, 0.1);
84 }
85 }
86
87 for (x = 0; x < map.Width; x += 2)
88 {
89 for (y = 0; y < map.Height; y += 2)
90 {
91 if (map[x, y] < 0.1)
92 map[x, y] = 0.1;
93 if (map[x, y] > 256)
94 map[x, y] = 256;
95 }
96 }
97 //smooth.FloodEffect(map, smoothMask, 4.0);
98 }
99
100 #endregion
101
102 private static void SetLowerChannel(ITerrainChannel map, bool[,] cliffMask, bool[,] channelMask, int x, int y, int numChannels, int channelWidth,
103 int mapSize, int rp)
104 {
105 for (int i = 0; i < numChannels; i++)
106 {
107 double distanceToLine = Math.Abs(rp - ((mapSize / numChannels) * i));
108
109 if (distanceToLine < channelWidth)
110 {
111 if (channelMask[x, y])
112 return;
113
114 // Remove channels
115 map[x, y] -= 10;
116 channelMask[x, y] = true;
117 }
118 if (distanceToLine < 1)
119 {
120 cliffMask[x, y] = true;
121 }
122 }
123 }
124 }
125}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/Effects/DefaultTerrainGenerator.cs b/OpenSim/Region/Environment/Modules/World/Terrain/Effects/DefaultTerrainGenerator.cs
deleted file mode 100644
index 2082137..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/Effects/DefaultTerrainGenerator.cs
+++ /dev/null
@@ -1,56 +0,0 @@
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 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 OpenSim.Framework;
28using OpenSim.Region.Framework.Interfaces;
29using OpenSim.Region.Framework.Scenes;
30
31namespace OpenSim.Region.Environment.Modules.World.Terrain.Effects
32{
33 internal class DefaultTerrainGenerator : ITerrainEffect
34 {
35 #region ITerrainEffect Members
36
37 public void RunEffect(ITerrainChannel map)
38 {
39 int x, y;
40 for (x = 0; x < map.Width; x++)
41 {
42 for (y = 0; y < map.Height; y++)
43 {
44 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10;
45 double spherFac = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2, Constants.RegionSize / 2, 50) * 0.01;
46 if (map[x, y] < spherFac)
47 {
48 map[x, y] = spherFac;
49 }
50 }
51 }
52 }
53
54 #endregion
55 }
56} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/BMP.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/BMP.cs
deleted file mode 100644
index a8e79d0..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/BMP.cs
+++ /dev/null
@@ -1,76 +0,0 @@
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 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 */
27
28using System.Drawing;
29using System.Drawing.Imaging;
30using System.IO;
31using OpenSim.Region.Framework.Interfaces;
32
33namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders
34{
35 /// <summary>
36 /// A generic windows bitmap loader.
37 /// Should be capable of handling 24-bit RGB images.
38 ///
39 /// Uses the System.Drawing filesystem loader.
40 /// </summary>
41 internal class BMP : GenericSystemDrawing
42 {
43 /// <summary>
44 /// Exports a file to a image on the disk using a System.Drawing exporter.
45 /// </summary>
46 /// <param name="filename">The target filename</param>
47 /// <param name="map">The terrain channel being saved</param>
48 public override void SaveFile(string filename, ITerrainChannel map)
49 {
50 Bitmap colours = CreateGrayscaleBitmapFromMap(map);
51
52 colours.Save(filename, ImageFormat.Bmp);
53 }
54
55 /// <summary>
56 /// Exports a stream using a System.Drawing exporter.
57 /// </summary>
58 /// <param name="stream">The target stream</param>
59 /// <param name="map">The terrain channel being saved</param>
60 public override void SaveStream(Stream stream, ITerrainChannel map)
61 {
62 Bitmap colours = CreateGrayscaleBitmapFromMap(map);
63
64 colours.Save(stream, ImageFormat.Png);
65 }
66
67 /// <summary>
68 /// The human readable version of the file format(s) this loader handles
69 /// </summary>
70 /// <returns></returns>
71 public override string ToString()
72 {
73 return "BMP";
74 }
75 }
76}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GIF.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GIF.cs
deleted file mode 100644
index b76fe05..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GIF.cs
+++ /dev/null
@@ -1,61 +0,0 @@
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 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 */
27
28using System.Drawing;
29using System.Drawing.Imaging;
30using System.IO;
31using OpenSim.Region.Framework.Interfaces;
32
33namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders
34{
35 internal class GIF : GenericSystemDrawing
36 {
37 public override void SaveFile(string filename, ITerrainChannel map)
38 {
39 Bitmap colours = CreateGrayscaleBitmapFromMap(map);
40
41 colours.Save(filename, ImageFormat.Gif);
42 }
43
44 /// <summary>
45 /// Exports a stream using a System.Drawing exporter.
46 /// </summary>
47 /// <param name="stream">The target stream</param>
48 /// <param name="map">The terrain channel being saved</param>
49 public override void SaveStream(Stream stream, ITerrainChannel map)
50 {
51 Bitmap colours = CreateGrayscaleBitmapFromMap(map);
52
53 colours.Save(stream, ImageFormat.Gif);
54 }
55
56 public override string ToString()
57 {
58 return "GIF";
59 }
60 }
61}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
deleted file mode 100644
index 80873d9..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ /dev/null
@@ -1,195 +0,0 @@
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 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 */
27
28using System;
29using System.Drawing;
30using System.Drawing.Imaging;
31using System.IO;
32using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes;
34
35namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders
36{
37 /// <summary>
38 /// A virtual class designed to have methods overloaded,
39 /// this class provides an interface for a generic image
40 /// saving and loading mechanism, but does not specify the
41 /// format. It should not be insubstantiated directly.
42 /// </summary>
43 public class GenericSystemDrawing : ITerrainLoader
44 {
45 #region ITerrainLoader Members
46
47 public string FileExtension
48 {
49 get { return ".gsd"; }
50 }
51
52 /// <summary>
53 /// Loads a file from a specified filename on the disk,
54 /// parses the image using the System.Drawing parsers
55 /// then returns a terrain channel. Values are
56 /// returned based on HSL brightness between 0m and 128m
57 /// </summary>
58 /// <param name="filename">The target image to load</param>
59 /// <returns>A terrain channel generated from the image.</returns>
60 public virtual ITerrainChannel LoadFile(string filename)
61 {
62 return LoadBitmap(new Bitmap(filename));
63 }
64
65 public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h)
66 {
67 throw new NotImplementedException();
68 }
69
70 public virtual ITerrainChannel LoadStream(Stream stream)
71 {
72 return LoadBitmap(new Bitmap(stream));
73 }
74
75 protected virtual ITerrainChannel LoadBitmap(Bitmap bitmap)
76 {
77 ITerrainChannel retval = new TerrainChannel(bitmap.Width, bitmap.Height);
78
79 int x;
80 for (x = 0; x < bitmap.Width; x++)
81 {
82 int y;
83 for (y = 0; y < bitmap.Height; y++)
84 {
85 retval[x, y] = bitmap.GetPixel(x, bitmap.Height - y - 1).GetBrightness() * 128;
86 }
87 }
88
89 return retval;
90 }
91
92 /// <summary>
93 /// Exports a file to a image on the disk using a System.Drawing exporter.
94 /// </summary>
95 /// <param name="filename">The target filename</param>
96 /// <param name="map">The terrain channel being saved</param>
97 public virtual void SaveFile(string filename, ITerrainChannel map)
98 {
99 Bitmap colours = CreateGrayscaleBitmapFromMap(map);
100
101 colours.Save(filename, ImageFormat.Png);
102 }
103
104 /// <summary>
105 /// Exports a stream using a System.Drawing exporter.
106 /// </summary>
107 /// <param name="stream">The target stream</param>
108 /// <param name="map">The terrain channel being saved</param>
109 public virtual void SaveStream(Stream stream, ITerrainChannel map)
110 {
111 Bitmap colours = CreateGrayscaleBitmapFromMap(map);
112
113 colours.Save(stream, ImageFormat.Png);
114 }
115
116 #endregion
117
118 public override string ToString()
119 {
120 return "SYS.DRAWING";
121 }
122
123 /// <summary>
124 /// Protected method, generates a grayscale bitmap
125 /// image from a specified terrain channel.
126 /// </summary>
127 /// <param name="map">The terrain channel to export to bitmap</param>
128 /// <returns>A System.Drawing.Bitmap containing a grayscale image</returns>
129 protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map)
130 {
131 Bitmap bmp = new Bitmap(map.Width, map.Height);
132
133 const int pallete = 256;
134
135 Color[] grays = new Color[pallete];
136 for (int i = 0; i < grays.Length; i++)
137 {
138 grays[i] = Color.FromArgb(i, i, i);
139 }
140
141 for (int y = 0; y < map.Height; y++)
142 {
143 for (int x = 0; x < map.Width; x++)
144 {
145 // 512 is the largest possible height before colours clamp
146 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 128.0), 0.0) * (pallete - 1));
147
148 // Handle error conditions
149 if (colorindex > pallete - 1 || colorindex < 0)
150 bmp.SetPixel(x, map.Height - y - 1, Color.Red);
151 else
152 bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]);
153 }
154 }
155 return bmp;
156 }
157
158 /// <summary>
159 /// Protected method, generates a coloured bitmap
160 /// image from a specified terrain channel.
161 /// </summary>
162 /// <param name="map">The terrain channel to export to bitmap</param>
163 /// <returns>A System.Drawing.Bitmap containing a coloured image</returns>
164 protected static Bitmap CreateBitmapFromMap(ITerrainChannel map)
165 {
166 Bitmap gradientmapLd = new Bitmap("defaultstripe.png");
167
168 int pallete = gradientmapLd.Height;
169
170 Bitmap bmp = new Bitmap(map.Width, map.Height);
171 Color[] colours = new Color[pallete];
172
173 for (int i = 0; i < pallete; i++)
174 {
175 colours[i] = gradientmapLd.GetPixel(0, i);
176 }
177
178 for (int y = 0; y < map.Height; y++)
179 {
180 for (int x = 0; x < map.Width; x++)
181 {
182 // 512 is the largest possible height before colours clamp
183 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 512.0), 0.0) * (pallete - 1));
184
185 // Handle error conditions
186 if (colorindex > pallete - 1 || colorindex < 0)
187 bmp.SetPixel(x, map.Height - y - 1, Color.Red);
188 else
189 bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]);
190 }
191 }
192 return bmp;
193 }
194 }
195}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/JPEG.cs
deleted file mode 100644
index bea504d..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/JPEG.cs
+++ /dev/null
@@ -1,112 +0,0 @@
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 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 */
27
28using System;
29using System.Drawing;
30using System.Drawing.Imaging;
31using System.IO;
32using OpenSim.Region.Framework.Interfaces;
33
34namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders
35{
36 public class JPEG : ITerrainLoader
37 {
38 #region ITerrainLoader Members
39
40 public string FileExtension
41 {
42 get { return ".jpg"; }
43 }
44
45 public ITerrainChannel LoadFile(string filename)
46 {
47 throw new NotImplementedException();
48 }
49
50 public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h)
51 {
52 throw new NotImplementedException();
53 }
54
55 public ITerrainChannel LoadStream(Stream stream)
56 {
57 throw new NotImplementedException();
58 }
59
60 public void SaveFile(string filename, ITerrainChannel map)
61 {
62 Bitmap colours = CreateBitmapFromMap(map);
63
64 colours.Save(filename, ImageFormat.Jpeg);
65 }
66
67 /// <summary>
68 /// Exports a stream using a System.Drawing exporter.
69 /// </summary>
70 /// <param name="stream">The target stream</param>
71 /// <param name="map">The terrain channel being saved</param>
72 public void SaveStream(Stream stream, ITerrainChannel map)
73 {
74 Bitmap colours = CreateBitmapFromMap(map);
75
76 colours.Save(stream, ImageFormat.Jpeg);
77 }
78
79 #endregion
80
81 public override string ToString()
82 {
83 return "JPEG";
84 }
85
86 private static Bitmap CreateBitmapFromMap(ITerrainChannel map)
87 {
88 Bitmap gradientmapLd = new Bitmap("defaultstripe.png");
89
90 int pallete = gradientmapLd.Height;
91
92 Bitmap bmp = new Bitmap(map.Width, map.Height);
93 Color[] colours = new Color[pallete];
94
95 for (int i = 0; i < pallete; i++)
96 {
97 colours[i] = gradientmapLd.GetPixel(0, i);
98 }
99
100 for (int y = 0; y < map.Height; y++)
101 {
102 for (int x = 0; x < map.Width; x++)
103 {
104 // 512 is the largest possible height before colours clamp
105 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 512.0), 0.0) * (pallete - 1));
106 bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]);
107 }
108 }
109 return bmp;
110 }
111 }
112}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/LLRAW.cs
deleted file mode 100644
index e323e28..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/LLRAW.cs
+++ /dev/null
@@ -1,250 +0,0 @@
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 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 */
27
28using System;
29using System.IO;
30using OpenSim.Region.Framework.Interfaces;
31using OpenSim.Region.Framework.Scenes;
32
33namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders
34{
35 public class LLRAW : ITerrainLoader
36 {
37 public struct HeightmapLookupValue : IComparable<HeightmapLookupValue>
38 {
39 public int Index;
40 public double Value;
41
42 public HeightmapLookupValue(int index, double value)
43 {
44 Index = index;
45 Value = value;
46 }
47
48 public int CompareTo(HeightmapLookupValue val)
49 {
50 return Value.CompareTo(val.Value);
51 }
52 }
53
54 /// <summary>Lookup table to speed up terrain exports</summary>
55 HeightmapLookupValue[] LookupHeightTable;
56
57 public LLRAW()
58 {
59 LookupHeightTable = new HeightmapLookupValue[256 * 256];
60
61 for (int i = 0; i < 256; i++)
62 {
63 for (int j = 0; j < 256; j++)
64 {
65 LookupHeightTable[i + (j * 256)] = new HeightmapLookupValue(i + (j * 256), ((double)i * ((double)j / 128.0d)));
66 }
67 }
68 Array.Sort<HeightmapLookupValue>(LookupHeightTable);
69 }
70
71 #region ITerrainLoader Members
72
73 public ITerrainChannel LoadFile(string filename)
74 {
75 FileInfo file = new FileInfo(filename);
76 FileStream s = file.Open(FileMode.Open, FileAccess.Read);
77 ITerrainChannel retval = LoadStream(s);
78
79 s.Close();
80
81 return retval;
82 }
83
84 public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight)
85 {
86 TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight);
87
88 FileInfo file = new FileInfo(filename);
89 FileStream s = file.Open(FileMode.Open, FileAccess.Read);
90 BinaryReader bs = new BinaryReader(s);
91
92 int currFileYOffset = fileHeight - 1;
93
94 // if our region isn't on the first Y section of the areas to be landscaped, then
95 // advance to our section of the file
96 while (currFileYOffset > offsetY)
97 {
98 // read a whole strip of regions
99 int heightsToRead = sectionHeight * (fileWidth * sectionWidth);
100 bs.ReadBytes(heightsToRead * 13); // because there are 13 fun channels
101 currFileYOffset--;
102 }
103
104 // got to the Y start offset within the file of our region
105 // so read the file bits associated with our region
106 int y;
107 // for each Y within our Y offset
108 for (y = sectionHeight - 1; y >= 0; y--)
109 {
110 int currFileXOffset = 0;
111
112 // if our region isn't the first X section of the areas to be landscaped, then
113 // advance the stream to the X start pos of our section in the file
114 // i.e. eat X upto where we start
115 while (currFileXOffset < offsetX)
116 {
117 bs.ReadBytes(sectionWidth * 13);
118 currFileXOffset++;
119 }
120
121 // got to our X offset, so write our regions X line
122 int x;
123 for (x = 0; x < sectionWidth; x++)
124 {
125 // Read a strip and continue
126 retval[x, y] = bs.ReadByte() * (bs.ReadByte() / 128.0);
127 bs.ReadBytes(11);
128 }
129 // record that we wrote it
130 currFileXOffset++;
131
132 // if our region isn't the last X section of the areas to be landscaped, then
133 // advance the stream to the end of this Y column
134 while (currFileXOffset < fileWidth)
135 {
136 // eat the next regions x line
137 bs.ReadBytes(sectionWidth * 13); //The 13 channels again
138 currFileXOffset++;
139 }
140 }
141
142 bs.Close();
143 s.Close();
144
145 return retval;
146 }
147
148 public ITerrainChannel LoadStream(Stream s)
149 {
150 TerrainChannel retval = new TerrainChannel();
151
152 BinaryReader bs = new BinaryReader(s);
153 int y;
154 for (y = 0; y < retval.Height; y++)
155 {
156 int x;
157 for (x = 0; x < retval.Width; x++)
158 {
159 retval[x, (retval.Height - 1) - y] = bs.ReadByte() * (bs.ReadByte() / 128.0);
160 bs.ReadBytes(11); // Advance the stream to next bytes.
161 }
162 }
163
164 bs.Close();
165
166 return retval;
167 }
168
169 public void SaveFile(string filename, ITerrainChannel map)
170 {
171 FileInfo file = new FileInfo(filename);
172 FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write);
173 SaveStream(s, map);
174
175 s.Close();
176 }
177
178 public void SaveStream(Stream s, ITerrainChannel map)
179 {
180 BinaryWriter binStream = new BinaryWriter(s);
181
182 // Output the calculated raw
183 for (int y = 0; y < map.Height; y++)
184 {
185 for (int x = 0; x < map.Width; x++)
186 {
187 double t = map[x, (map.Height - 1) - y];
188 //if height is less than 0, set it to 0 as
189 //can't save -ve values in a LLRAW file
190 if (t < 0d)
191 {
192 t = 0d;
193 }
194
195 int index = 0;
196
197 // The lookup table is pre-sorted, so we either find an exact match or
198 // the next closest (smaller) match with a binary search
199 index = Array.BinarySearch<HeightmapLookupValue>(LookupHeightTable, new HeightmapLookupValue(0, t));
200 if (index < 0)
201 index = ~index - 1;
202
203 index = LookupHeightTable[index].Index;
204
205 byte red = (byte) (index & 0xFF);
206 byte green = (byte) ((index >> 8) & 0xFF);
207 const byte blue = 20;
208 const byte alpha1 = 0;
209 const byte alpha2 = 0;
210 const byte alpha3 = 0;
211 const byte alpha4 = 0;
212 const byte alpha5 = 255;
213 const byte alpha6 = 255;
214 const byte alpha7 = 255;
215 const byte alpha8 = 255;
216 byte alpha9 = red;
217 byte alpha10 = green;
218
219 binStream.Write(red);
220 binStream.Write(green);
221 binStream.Write(blue);
222 binStream.Write(alpha1);
223 binStream.Write(alpha2);
224 binStream.Write(alpha3);
225 binStream.Write(alpha4);
226 binStream.Write(alpha5);
227 binStream.Write(alpha6);
228 binStream.Write(alpha7);
229 binStream.Write(alpha8);
230 binStream.Write(alpha9);
231 binStream.Write(alpha10);
232 }
233 }
234
235 binStream.Close();
236 }
237
238 public string FileExtension
239 {
240 get { return ".raw"; }
241 }
242
243 #endregion
244
245 public override string ToString()
246 {
247 return "LL/SL RAW";
248 }
249 }
250}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/PNG.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/PNG.cs
deleted file mode 100644
index 25967f3..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/PNG.cs
+++ /dev/null
@@ -1,61 +0,0 @@
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 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 */
27
28using System.Drawing;
29using System.Drawing.Imaging;
30using System.IO;
31using OpenSim.Region.Framework.Interfaces;
32
33namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders
34{
35 internal class PNG : GenericSystemDrawing
36 {
37 public override void SaveFile(string filename, ITerrainChannel map)
38 {
39 Bitmap colours = CreateGrayscaleBitmapFromMap(map);
40
41 colours.Save(filename, ImageFormat.Png);
42 }
43
44 /// <summary>
45 /// Exports a stream using a System.Drawing exporter.
46 /// </summary>
47 /// <param name="stream">The target stream</param>
48 /// <param name="map">The terrain channel being saved</param>
49 public override void SaveStream(Stream stream, ITerrainChannel map)
50 {
51 Bitmap colours = CreateGrayscaleBitmapFromMap(map);
52
53 colours.Save(stream, ImageFormat.Png);
54 }
55
56 public override string ToString()
57 {
58 return "PNG";
59 }
60 }
61}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/RAW32.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/RAW32.cs
deleted file mode 100644
index 7aff56a..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/RAW32.cs
+++ /dev/null
@@ -1,170 +0,0 @@
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 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 */
27
28using System.IO;
29using OpenSim.Region.Framework.Interfaces;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders
33{
34 public class RAW32 : ITerrainLoader
35 {
36 #region ITerrainLoader Members
37
38 public string FileExtension
39 {
40 get { return ".r32"; }
41 }
42
43 public ITerrainChannel LoadFile(string filename)
44 {
45 FileInfo file = new FileInfo(filename);
46 FileStream s = file.Open(FileMode.Open, FileAccess.Read);
47 ITerrainChannel retval = LoadStream(s);
48
49 s.Close();
50
51 return retval;
52 }
53
54 public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight)
55 {
56 TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight);
57
58 FileInfo file = new FileInfo(filename);
59 FileStream s = file.Open(FileMode.Open, FileAccess.Read);
60 BinaryReader bs = new BinaryReader(s);
61
62 int currFileYOffset = 0;
63
64 // if our region isn't on the first Y section of the areas to be landscaped, then
65 // advance to our section of the file
66 while (currFileYOffset < offsetY)
67 {
68 // read a whole strip of regions
69 int heightsToRead = sectionHeight * (fileWidth * sectionWidth);
70 bs.ReadBytes(heightsToRead * 4); // because the floats are 4 bytes in the file
71 currFileYOffset++;
72 }
73
74 // got to the Y start offset within the file of our region
75 // so read the file bits associated with our region
76 int y;
77 // for each Y within our Y offset
78 for (y = 0; y < sectionHeight; y++)
79 {
80 int currFileXOffset = 0;
81
82 // if our region isn't the first X section of the areas to be landscaped, then
83 // advance the stream to the X start pos of our section in the file
84 // i.e. eat X upto where we start
85 while (currFileXOffset < offsetX)
86 {
87 bs.ReadBytes(sectionWidth * 4); // 4 bytes = single
88 currFileXOffset++;
89 }
90
91 // got to our X offset, so write our regions X line
92 int x;
93 for (x = 0; x < sectionWidth; x++)
94 {
95 // Read a strip and continue
96 retval[x, y] = bs.ReadSingle();
97 }
98 // record that we wrote it
99 currFileXOffset++;
100
101 // if our region isn't the last X section of the areas to be landscaped, then
102 // advance the stream to the end of this Y column
103 while (currFileXOffset < fileWidth)
104 {
105 // eat the next regions x line
106 bs.ReadBytes(sectionWidth * 4); // 4 bytes = single
107 currFileXOffset++;
108 }
109 }
110
111 bs.Close();
112 s.Close();
113
114 return retval;
115 }
116
117 public ITerrainChannel LoadStream(Stream s)
118 {
119 TerrainChannel retval = new TerrainChannel();
120
121 BinaryReader bs = new BinaryReader(s);
122 int y;
123 for (y = 0; y < retval.Height; y++)
124 {
125 int x;
126 for (x = 0; x < retval.Width; x++)
127 {
128 retval[x, y] = bs.ReadSingle();
129 }
130 }
131
132 bs.Close();
133
134 return retval;
135 }
136
137 public void SaveFile(string filename, ITerrainChannel map)
138 {
139 FileInfo file = new FileInfo(filename);
140 FileStream s = file.Open(FileMode.Create, FileAccess.Write);
141 SaveStream(s, map);
142
143 s.Close();
144 }
145
146 public void SaveStream(Stream s, ITerrainChannel map)
147 {
148 BinaryWriter bs = new BinaryWriter(s);
149
150 int y;
151 for (y = 0; y < map.Height; y++)
152 {
153 int x;
154 for (x = 0; x < map.Width; x++)
155 {
156 bs.Write((float) map[x, y]);
157 }
158 }
159
160 bs.Close();
161 }
162
163 #endregion
164
165 public override string ToString()
166 {
167 return "RAW32";
168 }
169 }
170}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/TIFF.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/TIFF.cs
deleted file mode 100644
index 0503487..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/TIFF.cs
+++ /dev/null
@@ -1,61 +0,0 @@
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 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 */
27
28using System.Drawing;
29using System.Drawing.Imaging;
30using System.IO;
31using OpenSim.Region.Framework.Interfaces;
32
33namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders
34{
35 internal class TIFF : GenericSystemDrawing
36 {
37 public override void SaveFile(string filename, ITerrainChannel map)
38 {
39 Bitmap colours = CreateGrayscaleBitmapFromMap(map);
40
41 colours.Save(filename, ImageFormat.Tiff);
42 }
43
44 /// <summary>
45 /// Exports a stream using a System.Drawing exporter.
46 /// </summary>
47 /// <param name="stream">The target stream</param>
48 /// <param name="map">The terrain channel being saved</param>
49 public override void SaveStream(Stream stream, ITerrainChannel map)
50 {
51 Bitmap colours = CreateGrayscaleBitmapFromMap(map);
52
53 colours.Save(stream, ImageFormat.Tiff);
54 }
55
56 public override string ToString()
57 {
58 return "TIFF";
59 }
60 }
61}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/Terragen.cs
deleted file mode 100644
index 44d03e3..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/Terragen.cs
+++ /dev/null
@@ -1,142 +0,0 @@
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 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 */
27
28using System;
29using System.IO;
30using System.Text;
31using OpenSim.Region.Framework.Interfaces;
32using OpenSim.Region.Framework.Scenes;
33
34namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders
35{
36 /// <summary>
37 /// Terragen File Format Loader
38 /// Built from specification at
39 /// http://www.planetside.co.uk/terragen/dev/tgterrain.html
40 /// </summary>
41 internal class Terragen : ITerrainLoader
42 {
43 #region ITerrainLoader Members
44
45 public ITerrainChannel LoadFile(string filename)
46 {
47 FileInfo file = new FileInfo(filename);
48 FileStream s = file.Open(FileMode.Open, FileAccess.Read);
49 ITerrainChannel retval = LoadStream(s);
50
51 s.Close();
52
53 return retval;
54 }
55
56 public ITerrainChannel LoadStream(Stream s)
57 {
58 TerrainChannel retval = new TerrainChannel();
59
60 BinaryReader bs = new BinaryReader(s);
61
62 bool eof = false;
63 if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ")
64 {
65 int w = 256;
66 int h = 256;
67
68 // Terragen file
69 while (eof == false)
70 {
71 string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4));
72 switch (tmp)
73 {
74 case "SIZE":
75 int sztmp = bs.ReadInt16() + 1;
76 w = sztmp;
77 h = sztmp;
78 bs.ReadInt16();
79 break;
80 case "XPTS":
81 w = bs.ReadInt16();
82 bs.ReadInt16();
83 break;
84 case "YPTS":
85 h = bs.ReadInt16();
86 bs.ReadInt16();
87 break;
88 case "ALTW":
89 eof = true;
90 Int16 heightScale = bs.ReadInt16();
91 Int16 baseHeight = bs.ReadInt16();
92 retval = new TerrainChannel(w, h);
93 int x;
94 for (x = 0; x < w; x++)
95 {
96 int y;
97 for (y = 0; y < h; y++)
98 {
99 retval[x, y] = baseHeight + bs.ReadInt16() * (double) heightScale / 65536.0;
100 }
101 }
102 break;
103 default:
104 bs.ReadInt32();
105 break;
106 }
107 }
108 }
109
110 bs.Close();
111
112 return retval;
113 }
114
115 public void SaveFile(string filename, ITerrainChannel map)
116 {
117 throw new NotImplementedException();
118 }
119
120 public void SaveStream(Stream stream, ITerrainChannel map)
121 {
122 throw new NotImplementedException();
123 }
124
125 public string FileExtension
126 {
127 get { return ".ter"; }
128 }
129
130 public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h)
131 {
132 throw new NotImplementedException();
133 }
134
135 #endregion
136
137 public override string ToString()
138 {
139 return "Terragen";
140 }
141 }
142}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/FlattenArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/FlattenArea.cs
deleted file mode 100644
index 4d49a70..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/FlattenArea.cs
+++ /dev/null
@@ -1,70 +0,0 @@
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 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 */
27
28using OpenSim.Region.Framework.Interfaces;
29
30namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes
31{
32 public class FlattenArea : ITerrainFloodEffect
33 {
34 #region ITerrainFloodEffect Members
35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength)
37 {
38 double sum = 0.0;
39 double steps = 0.0;
40
41 int x, y;
42 for (x = 0; x < map.Width; x++)
43 {
44 for (y = 0; y < map.Height; y++)
45 {
46 if (fillArea[x, y])
47 {
48 sum += map[x, y];
49 steps += 1.0;
50 }
51 }
52 }
53
54 double avg = sum / steps;
55
56 double str = 0.1 * strength; // == 0.2 in the default client
57
58 for (x = 0; x < map.Width; x++)
59 {
60 for (y = 0; y < map.Height; y++)
61 {
62 if (fillArea[x, y])
63 map[x, y] = (map[x, y] * (1.0 - str)) + (avg * str);
64 }
65 }
66 }
67
68 #endregion
69 }
70} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/LowerArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/LowerArea.cs
deleted file mode 100644
index 64f9014..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/LowerArea.cs
+++ /dev/null
@@ -1,54 +0,0 @@
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 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 */
27
28using OpenSim.Region.Framework.Interfaces;
29
30namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes
31{
32 public class LowerArea : ITerrainFloodEffect
33 {
34 #region ITerrainFloodEffect Members
35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength)
37 {
38 int x;
39 for (x = 0; x < map.Width; x++)
40 {
41 int y;
42 for (y = 0; y < map.Height; y++)
43 {
44 if (fillArea[x, y])
45 {
46 map[x, y] -= strength;
47 }
48 }
49 }
50 }
51
52 #endregion
53 }
54} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/NoiseArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/NoiseArea.cs
deleted file mode 100644
index 2d44a3a..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/NoiseArea.cs
+++ /dev/null
@@ -1,58 +0,0 @@
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 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 */
27
28using OpenSim.Framework;
29using OpenSim.Region.Framework.Interfaces;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes
33{
34 public class NoiseArea : ITerrainFloodEffect
35 {
36 #region ITerrainFloodEffect Members
37
38 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength)
39 {
40 int x;
41 for (x = 0; x < map.Width; x++)
42 {
43 int y;
44 for (y = 0; y < map.Height; y++)
45 {
46 if (fillArea[x, y])
47 {
48 double noise = TerrainUtil.PerlinNoise2D((double) x / Constants.RegionSize, (double) y / Constants.RegionSize, 8, 1.0);
49
50 map[x, y] += noise * strength;
51 }
52 }
53 }
54 }
55
56 #endregion
57 }
58} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RaiseArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RaiseArea.cs
deleted file mode 100644
index 0c7d016..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RaiseArea.cs
+++ /dev/null
@@ -1,54 +0,0 @@
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 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 */
27
28using OpenSim.Region.Framework.Interfaces;
29
30namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes
31{
32 public class RaiseArea : ITerrainFloodEffect
33 {
34 #region ITerrainFloodEffect Members
35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength)
37 {
38 int x;
39 for (x = 0; x < map.Width; x++)
40 {
41 int y;
42 for (y = 0; y < map.Height; y++)
43 {
44 if (fillArea[x, y])
45 {
46 map[x, y] += strength;
47 }
48 }
49 }
50 }
51
52 #endregion
53 }
54} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RevertArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RevertArea.cs
deleted file mode 100644
index 3f06d82..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RevertArea.cs
+++ /dev/null
@@ -1,67 +0,0 @@
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 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 */
27
28using OpenSim.Region.Framework.Interfaces;
29
30namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes
31{
32 public class RevertArea : ITerrainFloodEffect
33 {
34 private readonly ITerrainChannel m_revertmap;
35
36 public RevertArea(ITerrainChannel revertmap)
37 {
38 m_revertmap = revertmap;
39 }
40
41 #region ITerrainFloodEffect Members
42
43 /// <summary>
44 /// reverts an area of the map to the heightfield stored in the revertmap
45 /// </summary>
46 /// <param name="map">the current heightmap</param>
47 /// <param name="fillArea">array indicating which sections of the map are to be reverted</param>
48 /// <param name="strength">unused</param>
49 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength)
50 {
51 int x;
52 for (x = 0; x < map.Width; x++)
53 {
54 int y;
55 for (y = 0; y < map.Height; y++)
56 {
57 if (fillArea[x, y])
58 {
59 map[x, y] = m_revertmap[x, y];
60 }
61 }
62 }
63 }
64
65 #endregion
66 }
67}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/SmoothArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/SmoothArea.cs
deleted file mode 100644
index 3881264..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/SmoothArea.cs
+++ /dev/null
@@ -1,114 +0,0 @@
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 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 */
27
28using OpenSim.Region.Framework.Interfaces;
29
30namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes
31{
32 public class SmoothArea : ITerrainFloodEffect
33 {
34 #region ITerrainFloodEffect Members
35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength)
37 {
38 double area = strength;
39 double step = strength / 4.0;
40
41 double[,] manipulate = new double[map.Width,map.Height];
42 int x, y;
43 for (x = 0; x < map.Width; x++)
44 {
45 for (y = 0; y < map.Height; y++)
46 {
47 if (!fillArea[x, y])
48 continue;
49
50 double average = 0.0;
51 int avgsteps = 0;
52
53 double n;
54 for (n = 0.0 - area; n < area; n += step)
55 {
56 double l;
57 for (l = 0.0 - area; l < area; l += step)
58 {
59 avgsteps++;
60 average += GetBilinearInterpolate(x + n, y + l, map);
61 }
62 }
63
64 manipulate[x, y] = average / avgsteps;
65 }
66 }
67 for (x = 0; x < map.Width; x++)
68 {
69 for (y = 0; y < map.Height; y++)
70 {
71 if (!fillArea[x, y])
72 continue;
73
74 map[x, y] = manipulate[x, y];
75 }
76 }
77 }
78
79 #endregion
80
81 private static double GetBilinearInterpolate(double x, double y, ITerrainChannel map)
82 {
83 int w = map.Width;
84 int h = map.Height;
85
86 if (x > w - 2.0)
87 x = w - 2.0;
88 if (y > h - 2.0)
89 y = h - 2.0;
90 if (x < 0.0)
91 x = 0.0;
92 if (y < 0.0)
93 y = 0.0;
94
95 const int stepSize = 1;
96 double h00 = map[(int) x, (int) y];
97 double h10 = map[(int) x + stepSize, (int) y];
98 double h01 = map[(int) x, (int) y + stepSize];
99 double h11 = map[(int) x + stepSize, (int) y + stepSize];
100 double h1 = h00;
101 double h2 = h10;
102 double h3 = h01;
103 double h4 = h11;
104 double a00 = h1;
105 double a10 = h2 - h1;
106 double a01 = h3 - h1;
107 double a11 = h1 - h2 - h3 + h4;
108 double partialx = x - (int) x;
109 double partialz = y - (int) y;
110 double hi = a00 + (a10 * partialx) + (a01 * partialz) + (a11 * partialx * partialz);
111 return hi;
112 }
113 }
114} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainEffect.cs b/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainEffect.cs
deleted file mode 100644
index 4533e9e..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainEffect.cs
+++ /dev/null
@@ -1,36 +0,0 @@
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 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 */
27
28using OpenSim.Region.Framework.Interfaces;
29
30namespace OpenSim.Region.Environment.Modules.World.Terrain
31{
32 public interface ITerrainEffect
33 {
34 void RunEffect(ITerrainChannel map);
35 }
36} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainFloodEffect.cs b/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainFloodEffect.cs
deleted file mode 100644
index 5bae84b..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainFloodEffect.cs
+++ /dev/null
@@ -1,37 +0,0 @@
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 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 */
27
28using System;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.Environment.Modules.World.Terrain
32{
33 public interface ITerrainFloodEffect
34 {
35 void FloodEffect(ITerrainChannel map, Boolean[,] fillArea, double strength);
36 }
37} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainLoader.cs b/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainLoader.cs
deleted file mode 100644
index 21bda58..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainLoader.cs
+++ /dev/null
@@ -1,42 +0,0 @@
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 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 */
27
28using System.IO;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.Environment.Modules.World.Terrain
32{
33 public interface ITerrainLoader
34 {
35 string FileExtension { get; }
36 ITerrainChannel LoadFile(string filename);
37 ITerrainChannel LoadFile(string filename, int fileStartX, int fileStartY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight);
38 ITerrainChannel LoadStream(Stream stream);
39 void SaveFile(string filename, ITerrainChannel map);
40 void SaveStream(Stream stream, ITerrainChannel map);
41 }
42} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainModule.cs b/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainModule.cs
deleted file mode 100644
index 91bc31f..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainModule.cs
+++ /dev/null
@@ -1,61 +0,0 @@
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 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 */
27
28
29using System.IO;
30using OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Region.Environment.Modules.World.Terrain
34{
35 public interface ITerrainModule
36 {
37 void LoadFromFile(string filename);
38 void SaveToFile(string filename);
39 void ModifyTerrain(UUID user, Vector3 pos, byte size, byte action, UUID agentId);
40
41 /// <summary>
42 /// Load a terrain from a stream.
43 /// </summary>
44 /// <param name="filename">
45 /// Only required here to identify the image type. Not otherwise used in the loading itself.
46 /// </param>
47 /// <param name="stream"></param>
48 void LoadFromStream(string filename, Stream stream);
49
50 /// <summary>
51 /// Save a terrain to a stream.
52 /// </summary>
53 /// <param name="filename">
54 /// Only required here to identify the image type. Not otherwise used in the saving itself.
55 /// </param>
56 /// <param name="stream"></param>
57 void SaveToStream(string filename, Stream stream);
58
59 void InstallPlugin(string name, ITerrainEffect plug);
60 }
61}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainPaintableEffect.cs b/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainPaintableEffect.cs
deleted file mode 100644
index 7461560..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainPaintableEffect.cs
+++ /dev/null
@@ -1,36 +0,0 @@
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 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 */
27
28using OpenSim.Region.Framework.Interfaces;
29
30namespace OpenSim.Region.Environment.Modules.World.Terrain
31{
32 public interface ITerrainPaintableEffect
33 {
34 void PaintEffect(ITerrainChannel map, bool[,] allowMask, double x, double y, double z, double strength, double duration);
35 }
36}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs
deleted file mode 100644
index 4d694cc..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs
+++ /dev/null
@@ -1,318 +0,0 @@
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 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 */
27
28using System;
29using OpenSim.Region.Framework.Interfaces;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes
33{
34 /// <summary>
35 /// Hydraulic Erosion Brush
36 /// </summary>
37 public class ErodeSphere : ITerrainPaintableEffect
38 {
39 private const double rainHeight = 0.2;
40 private const int rounds = 10;
41 private const NeighbourSystem type = NeighbourSystem.Moore;
42 private const double waterSaturation = 0.30;
43
44 #region Supporting Functions
45
46 private static int[] Neighbours(NeighbourSystem neighbourType, int index)
47 {
48 int[] coord = new int[2];
49
50 index++;
51
52 switch (neighbourType)
53 {
54 case NeighbourSystem.Moore:
55 switch (index)
56 {
57 case 1:
58 coord[0] = -1;
59 coord[1] = -1;
60 break;
61
62 case 2:
63 coord[0] = -0;
64 coord[1] = -1;
65 break;
66
67 case 3:
68 coord[0] = +1;
69 coord[1] = -1;
70 break;
71
72 case 4:
73 coord[0] = -1;
74 coord[1] = -0;
75 break;
76
77 case 5:
78 coord[0] = -0;
79 coord[1] = -0;
80 break;
81
82 case 6:
83 coord[0] = +1;
84 coord[1] = -0;
85 break;
86
87 case 7:
88 coord[0] = -1;
89 coord[1] = +1;
90 break;
91
92 case 8:
93 coord[0] = -0;
94 coord[1] = +1;
95 break;
96
97 case 9:
98 coord[0] = +1;
99 coord[1] = +1;
100 break;
101
102 default:
103 break;
104 }
105 break;
106
107 case NeighbourSystem.VonNeumann:
108 switch (index)
109 {
110 case 1:
111 coord[0] = 0;
112 coord[1] = -1;
113 break;
114
115 case 2:
116 coord[0] = -1;
117 coord[1] = 0;
118 break;
119
120 case 3:
121 coord[0] = +1;
122 coord[1] = 0;
123 break;
124
125 case 4:
126 coord[0] = 0;
127 coord[1] = +1;
128 break;
129
130 case 5:
131 coord[0] = -0;
132 coord[1] = -0;
133 break;
134
135 default:
136 break;
137 }
138 break;
139 }
140
141 return coord;
142 }
143
144 private enum NeighbourSystem
145 {
146 Moore,
147 VonNeumann
148 } ;
149
150 #endregion
151
152 #region ITerrainPaintableEffect Members
153
154 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration)
155 {
156 strength = TerrainUtil.MetersToSphericalStrength(strength);
157
158 int x, y;
159 // Using one 'rain' round for this, so skipping a useless loop
160 // Will need to adapt back in for the Flood brush
161
162 ITerrainChannel water = new TerrainChannel(map.Width, map.Height);
163 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height);
164
165 // Fill with rain
166 for (x = 0; x < water.Width; x++)
167 for (y = 0; y < water.Height; y++)
168 water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration);
169
170 for (int i = 0; i < rounds; i++)
171 {
172 // Erode underlying terrain
173 for (x = 0; x < water.Width; x++)
174 {
175 for (y = 0; y < water.Height; y++)
176 {
177 if (mask[x,y])
178 {
179 const double solConst = (1.0 / rounds);
180 double sedDelta = water[x, y] * solConst;
181 map[x, y] -= sedDelta;
182 sediment[x, y] += sedDelta;
183 }
184 }
185 }
186
187 // Move water
188 for (x = 0; x < water.Width; x++)
189 {
190 for (y = 0; y < water.Height; y++)
191 {
192 if (water[x, y] <= 0)
193 continue;
194
195 // Step 1. Calculate average of neighbours
196
197 int neighbours = 0;
198 double altitudeTotal = 0.0;
199 double altitudeMe = map[x, y] + water[x, y];
200
201 const int NEIGHBOUR_ME = 4;
202 const int NEIGHBOUR_MAX = 9;
203
204 for (int j = 0; j < NEIGHBOUR_MAX; j++)
205 {
206 if (j != NEIGHBOUR_ME)
207 {
208 int[] coords = Neighbours(type, j);
209
210 coords[0] += x;
211 coords[1] += y;
212
213 if (coords[0] > map.Width - 1)
214 continue;
215 if (coords[1] > map.Height - 1)
216 continue;
217 if (coords[0] < 0)
218 continue;
219 if (coords[1] < 0)
220 continue;
221
222 // Calculate total height of this neighbour
223 double altitudeNeighbour = water[coords[0], coords[1]] + map[coords[0], coords[1]];
224
225 // If it's greater than me...
226 if (altitudeNeighbour - altitudeMe < 0)
227 {
228 // Add it to our calculations
229 neighbours++;
230 altitudeTotal += altitudeNeighbour;
231 }
232 }
233 }
234
235 if (neighbours == 0)
236 continue;
237
238 double altitudeAvg = altitudeTotal / neighbours;
239
240 // Step 2. Allocate water to neighbours.
241 for (int j = 0; j < NEIGHBOUR_MAX; j++)
242 {
243 if (j != NEIGHBOUR_ME)
244 {
245 int[] coords = Neighbours(type, j);
246
247 coords[0] += x;
248 coords[1] += y;
249
250 if (coords[0] > map.Width - 1)
251 continue;
252 if (coords[1] > map.Height - 1)
253 continue;
254 if (coords[0] < 0)
255 continue;
256 if (coords[1] < 0)
257 continue;
258
259 // Skip if we dont have water to begin with.
260 if (water[x, y] < 0)
261 continue;
262
263 // Calculate our delta average
264 double altitudeDelta = altitudeMe - altitudeAvg;
265
266 if (altitudeDelta < 0)
267 continue;
268
269 // Calculate how much water we can move
270 double waterMin = Math.Min(water[x, y], altitudeDelta);
271 double waterDelta = waterMin * ((water[coords[0], coords[1]] + map[coords[0], coords[1]])
272 / altitudeTotal);
273
274 double sedimentDelta = sediment[x, y] * (waterDelta / water[x, y]);
275
276 if (sedimentDelta > 0)
277 {
278 sediment[x, y] -= sedimentDelta;
279 sediment[coords[0], coords[1]] += sedimentDelta;
280 }
281 }
282 }
283 }
284 }
285
286 // Evaporate
287
288 for (x = 0; x < water.Width; x++)
289 {
290 for (y = 0; y < water.Height; y++)
291 {
292 water[x, y] *= 1.0 - (rainHeight / rounds);
293
294 double waterCapacity = waterSaturation * water[x, y];
295
296 double sedimentDeposit = sediment[x, y] - waterCapacity;
297 if (sedimentDeposit > 0)
298 {
299 if (mask[x,y])
300 {
301 sediment[x, y] -= sedimentDeposit;
302 map[x, y] += sedimentDeposit;
303 }
304 }
305 }
306 }
307 }
308
309 // Deposit any remainder (should be minimal)
310 for (x = 0; x < water.Width; x++)
311 for (y = 0; y < water.Height; y++)
312 if (mask[x,y] && sediment[x, y] > 0)
313 map[x, y] += sediment[x, y];
314 }
315
316 #endregion
317 }
318}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/FlattenSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/FlattenSphere.cs
deleted file mode 100644
index 91c030d..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/FlattenSphere.cs
+++ /dev/null
@@ -1,101 +0,0 @@
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 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 */
27
28using System;
29using OpenSim.Region.Framework.Interfaces;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes
33{
34 public class FlattenSphere : ITerrainPaintableEffect
35 {
36 #region ITerrainPaintableEffect Members
37
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration)
39 {
40 strength = TerrainUtil.MetersToSphericalStrength(strength);
41
42 int x, y;
43
44 if (rz < 0) {
45 double sum = 0.0;
46 double step2 = 0.0;
47 duration = 0.009; //MCP Should be read from ini file
48
49
50 // compute delta map
51 for (x = 0; x < map.Width; x++)
52 {
53 for (y = 0; y < map.Height; y++)
54 {
55 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
56
57 if (z > 0) // add in non-zero amount
58 {
59 sum += map[x, y] * z;
60 step2 += z;
61 }
62 }
63 }
64 rz = sum / step2;
65 }
66
67
68 // blend in map
69 for (x = 0; x < map.Width; x++)
70 {
71 for (y = 0; y < map.Height; y++)
72 {
73 if (!mask[x,y])
74 continue;
75
76 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * duration;
77
78 if (z > 0) // add in non-zero amount
79 {
80 if (z > 1.0)
81 z = 1.0;
82
83 map[x, y] = (map[x, y] * (1.0 - z)) + (rz * z);
84 }
85
86 double delta = rz - map[x, y];
87 if (Math.Abs(delta) > 0.1)
88 delta *= 0.25;
89
90 if (delta != 0) // add in non-zero amount
91 {
92 map[x, y] += delta;
93 }
94
95 }
96 }
97 }
98
99 #endregion
100 }
101}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/LowerSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/LowerSphere.cs
deleted file mode 100644
index d391e94..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/LowerSphere.cs
+++ /dev/null
@@ -1,84 +0,0 @@
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 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 */
27
28using System;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes
32{
33 public class LowerSphere : ITerrainPaintableEffect
34 {
35 #region ITerrainPaintableEffect Members
36
37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration)
38 {
39 int s = (int) (Math.Pow(2, strength) + 0.5);
40
41 int x;
42 int xFrom = (int)(rx-s+0.5);
43 int xTo = (int)(rx+s+0.5) + 1;
44 int yFrom = (int)(ry-s+0.5);
45 int yTo = (int)(ry+s+0.5) + 1;
46
47 if (xFrom < 0)
48 xFrom = 0;
49
50 if (yFrom < 0)
51 yFrom = 0;
52
53 if (xTo > map.Width)
54 xTo = map.Width;
55
56 if (yTo > map.Width)
57 yTo = map.Width;
58
59 for (x = xFrom; x < xTo; x++)
60 {
61 int y;
62 for (y = yFrom; y < yTo; y++)
63 {
64 if (!mask[x,y])
65 continue;
66
67 // Calculate a cos-sphere and add it to the heighmap
68 double r = Math.Sqrt((x-rx) * (x-rx) + ((y-ry) * (y-ry)));
69 double z = Math.Cos(r * Math.PI / (s * 2));
70 if (z > 0.0)
71 {
72 double newz = map[x, y] - z * duration;
73 if (newz < 0.0)
74 map[x, y] = 0.0;
75 else
76 map[x, y] = newz;
77 }
78 }
79 }
80
81 }
82 #endregion
83 }
84}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/NoiseSphere.cs
deleted file mode 100644
index 32a6869..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/NoiseSphere.cs
+++ /dev/null
@@ -1,67 +0,0 @@
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 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 */
27
28using System;
29using OpenSim.Framework;
30using OpenSim.Region.Framework.Interfaces;
31using OpenSim.Region.Framework.Scenes;
32
33namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes
34{
35 public class NoiseSphere : ITerrainPaintableEffect
36 {
37 #region ITerrainPaintableEffect Members
38
39 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration)
40 {
41 strength = TerrainUtil.MetersToSphericalStrength(strength);
42
43 int x;
44 for (x = 0; x < map.Width; x++)
45 {
46 int y;
47 for (y = 0; y < map.Height; y++)
48 {
49 if (!mask[x,y])
50 continue;
51
52 // Calculate a sphere and add it to the heighmap
53 double z = strength;
54 z *= z;
55 z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry));
56
57 double noise = TerrainUtil.PerlinNoise2D(x / (double) Constants.RegionSize, y / (double) Constants.RegionSize, 8, 1.0);
58
59 if (z > 0.0)
60 map[x, y] += noise * z * duration;
61 }
62 }
63 }
64
65 #endregion
66 }
67}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/OlsenSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/OlsenSphere.cs
deleted file mode 100644
index 86d01d3..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/OlsenSphere.cs
+++ /dev/null
@@ -1,223 +0,0 @@
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 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 */
27
28using System;
29using OpenSim.Region.Framework.Interfaces;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes
33{
34 /// <summary>
35 /// Speed-Optimised Hybrid Erosion Brush
36 ///
37 /// As per Jacob Olsen's Paper
38 /// http://www.oddlabs.com/download/terrain_generation.pdf
39 /// </summary>
40 public class OlsenSphere : ITerrainPaintableEffect
41 {
42 private const double nConst = 1024.0;
43 private const NeighbourSystem type = NeighbourSystem.Moore;
44
45 #region Supporting Functions
46
47 private static int[] Neighbours(NeighbourSystem neighbourType, int index)
48 {
49 int[] coord = new int[2];
50
51 index++;
52
53 switch (neighbourType)
54 {
55 case NeighbourSystem.Moore:
56 switch (index)
57 {
58 case 1:
59 coord[0] = -1;
60 coord[1] = -1;
61 break;
62
63 case 2:
64 coord[0] = -0;
65 coord[1] = -1;
66 break;
67
68 case 3:
69 coord[0] = +1;
70 coord[1] = -1;
71 break;
72
73 case 4:
74 coord[0] = -1;
75 coord[1] = -0;
76 break;
77
78 case 5:
79 coord[0] = -0;
80 coord[1] = -0;
81 break;
82
83 case 6:
84 coord[0] = +1;
85 coord[1] = -0;
86 break;
87
88 case 7:
89 coord[0] = -1;
90 coord[1] = +1;
91 break;
92
93 case 8:
94 coord[0] = -0;
95 coord[1] = +1;
96 break;
97
98 case 9:
99 coord[0] = +1;
100 coord[1] = +1;
101 break;
102
103 default:
104 break;
105 }
106 break;
107
108 case NeighbourSystem.VonNeumann:
109 switch (index)
110 {
111 case 1:
112 coord[0] = 0;
113 coord[1] = -1;
114 break;
115
116 case 2:
117 coord[0] = -1;
118 coord[1] = 0;
119 break;
120
121 case 3:
122 coord[0] = +1;
123 coord[1] = 0;
124 break;
125
126 case 4:
127 coord[0] = 0;
128 coord[1] = +1;
129 break;
130
131 case 5:
132 coord[0] = -0;
133 coord[1] = -0;
134 break;
135
136 default:
137 break;
138 }
139 break;
140 }
141
142 return coord;
143 }
144
145 private enum NeighbourSystem
146 {
147 Moore,
148 VonNeumann
149 } ;
150
151 #endregion
152
153 #region ITerrainPaintableEffect Members
154
155 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration)
156 {
157 strength = TerrainUtil.MetersToSphericalStrength(strength);
158
159 int x;
160
161 for (x = 0; x < map.Width; x++)
162 {
163 int y;
164 for (y = 0; y < map.Height; y++)
165 {
166 if (!mask[x,y])
167 continue;
168
169 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
170
171 if (z > 0) // add in non-zero amount
172 {
173 const int NEIGHBOUR_ME = 4;
174 const int NEIGHBOUR_MAX = 9;
175
176 double max = Double.MinValue;
177 int loc = 0;
178
179
180 for (int j = 0; j < NEIGHBOUR_MAX; j++)
181 {
182 if (j != NEIGHBOUR_ME)
183 {
184 int[] coords = Neighbours(type, j);
185
186 coords[0] += x;
187 coords[1] += y;
188
189 if (coords[0] > map.Width - 1)
190 continue;
191 if (coords[1] > map.Height - 1)
192 continue;
193 if (coords[0] < 0)
194 continue;
195 if (coords[1] < 0)
196 continue;
197
198 double cellmax = map[x, y] - map[coords[0], coords[1]];
199 if (cellmax > max)
200 {
201 max = cellmax;
202 loc = j;
203 }
204 }
205 }
206
207 double T = nConst / ((map.Width + map.Height) / 2.0);
208 // Apply results
209 if (0 < max && max <= T)
210 {
211 int[] maxCoords = Neighbours(type, loc);
212 double heightDelta = 0.5 * max * z * duration;
213 map[x, y] -= heightDelta;
214 map[x + maxCoords[0], y + maxCoords[1]] += heightDelta;
215 }
216 }
217 }
218 }
219 }
220
221 #endregion
222 }
223}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RaiseSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RaiseSphere.cs
deleted file mode 100644
index a0ff262..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RaiseSphere.cs
+++ /dev/null
@@ -1,80 +0,0 @@
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 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 */
27
28using System;
29using OpenSim.Region.Framework.Interfaces;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes
33{
34 public class RaiseSphere : ITerrainPaintableEffect
35 {
36 #region ITerrainPaintableEffect Members
37
38
39 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration)
40 {
41 int s = (int) (Math.Pow(2, strength) + 0.5);
42
43 int x;
44 int xFrom = (int)(rx-s+0.5);
45 int xTo = (int)(rx+s+0.5) + 1;
46 int yFrom = (int)(ry-s+0.5);
47 int yTo = (int)(ry+s+0.5) + 1;
48
49 if (xFrom < 0)
50 xFrom = 0;
51
52 if (yFrom < 0)
53 yFrom = 0;
54
55 if (xTo > map.Width)
56 xTo = map.Width;
57
58 if (yTo > map.Width)
59 yTo = map.Width;
60
61 for (x = xFrom; x < xTo; x++)
62 {
63 int y;
64 for (y = yFrom; y < yTo; y++)
65 {
66 if (!mask[x,y])
67 continue;
68
69 // Calculate a cos-sphere and add it to the heighmap
70 double r = Math.Sqrt((x-rx) * (x-rx) + ((y-ry) * (y-ry)));
71 double z = Math.Cos(r * Math.PI / (s * 2));
72 if (z > 0.0)
73 map[x, y] += z * duration;
74 }
75 }
76 }
77
78 #endregion
79 }
80}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RevertSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RevertSphere.cs
deleted file mode 100644
index af6d94d..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RevertSphere.cs
+++ /dev/null
@@ -1,80 +0,0 @@
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 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 */
27
28using System;
29using OpenSim.Region.Framework.Interfaces;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes
33{
34 public class RevertSphere : ITerrainPaintableEffect
35 {
36 private readonly ITerrainChannel m_revertmap;
37
38 public RevertSphere(ITerrainChannel revertmap)
39 {
40 m_revertmap = revertmap;
41 }
42
43 #region ITerrainPaintableEffect Members
44
45 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration)
46 {
47 strength = TerrainUtil.MetersToSphericalStrength(strength);
48 duration = 0.03; //MCP Should be read from ini file
49
50 if (duration > 1.0)
51 duration = 1.0;
52 if (duration < 0)
53 return;
54
55 int x;
56 for (x = 0; x < map.Width; x++)
57 {
58 int y;
59 for (y = 0; y < map.Height; y++)
60 {
61 if (!mask[x,y])
62 continue;
63
64 // Calculate a sphere and add it to the heighmap
65 double z = strength;
66 z *= z;
67 z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry));
68
69 if (z > 0.0)
70 {
71 z *= duration;
72 map[x, y] = (map[x, y] * (1.0 - z)) + (m_revertmap[x, y] * z);
73 }
74 }
75 }
76 }
77
78 #endregion
79 }
80}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/SmoothSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/SmoothSphere.cs
deleted file mode 100644
index fe270f7..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/SmoothSphere.cs
+++ /dev/null
@@ -1,100 +0,0 @@
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 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 */
27
28using OpenSim.Region.Framework.Interfaces;
29using OpenSim.Region.Framework.Scenes;
30
31namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes
32{
33 public class SmoothSphere : ITerrainPaintableEffect
34 {
35 #region ITerrainPaintableEffect Members
36
37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration)
38 {
39 strength = TerrainUtil.MetersToSphericalStrength(strength);
40
41 int x, y;
42 double[,] tweak = new double[map.Width,map.Height];
43
44 double area = strength;
45 double step = strength / 4.0;
46 duration = 0.03; //MCP Should be read from ini file
47
48
49 // compute delta map
50 for (x = 0; x < map.Width; x++)
51 {
52 for (y = 0; y < map.Height; y++)
53 {
54 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
55
56 if (z > 0) // add in non-zero amount
57 {
58 double average = 0.0;
59 int avgsteps = 0;
60
61 double n;
62 for (n = 0.0 - area; n < area; n += step)
63 {
64 double l;
65 for (l = 0.0 - area; l < area; l += step)
66 {
67 avgsteps++;
68 average += TerrainUtil.GetBilinearInterpolate(x + n, y + l, map);
69 }
70 }
71 tweak[x, y] = average / avgsteps;
72 }
73 }
74 }
75 // blend in map
76 for (x = 0; x < map.Width; x++)
77 {
78 for (y = 0; y < map.Height; y++)
79 {
80 if (!mask[x,y])
81 continue;
82
83 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
84
85 if (z > 0) // add in non-zero amount
86 {
87 double da = z;
88 double a = (map[x, y] - tweak[x, y]) * da;
89 double newz = map[x, y] - (a * duration);
90
91 if (newz > 0.0)
92 map[x, y] = newz;
93 }
94 }
95 }
96 }
97
98 #endregion
99 }
100}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/WeatherSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/WeatherSphere.cs
deleted file mode 100644
index faba119..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/WeatherSphere.cs
+++ /dev/null
@@ -1,211 +0,0 @@
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 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 */
27
28using OpenSim.Region.Framework.Interfaces;
29using OpenSim.Region.Framework.Scenes;
30
31namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes
32{
33 /// <summary>
34 /// Thermal Weathering Paint Brush
35 /// </summary>
36 public class WeatherSphere : ITerrainPaintableEffect
37 {
38 private const double talus = 0.2;
39 private const NeighbourSystem type = NeighbourSystem.Moore;
40
41 #region Supporting Functions
42
43 private static int[] Neighbours(NeighbourSystem neighbourType, int index)
44 {
45 int[] coord = new int[2];
46
47 index++;
48
49 switch (neighbourType)
50 {
51 case NeighbourSystem.Moore:
52 switch (index)
53 {
54 case 1:
55 coord[0] = -1;
56 coord[1] = -1;
57 break;
58
59 case 2:
60 coord[0] = -0;
61 coord[1] = -1;
62 break;
63
64 case 3:
65 coord[0] = +1;
66 coord[1] = -1;
67 break;
68
69 case 4:
70 coord[0] = -1;
71 coord[1] = -0;
72 break;
73
74 case 5:
75 coord[0] = -0;
76 coord[1] = -0;
77 break;
78
79 case 6:
80 coord[0] = +1;
81 coord[1] = -0;
82 break;
83
84 case 7:
85 coord[0] = -1;
86 coord[1] = +1;
87 break;
88
89 case 8:
90 coord[0] = -0;
91 coord[1] = +1;
92 break;
93
94 case 9:
95 coord[0] = +1;
96 coord[1] = +1;
97 break;
98
99 default:
100 break;
101 }
102 break;
103
104 case NeighbourSystem.VonNeumann:
105 switch (index)
106 {
107 case 1:
108 coord[0] = 0;
109 coord[1] = -1;
110 break;
111
112 case 2:
113 coord[0] = -1;
114 coord[1] = 0;
115 break;
116
117 case 3:
118 coord[0] = +1;
119 coord[1] = 0;
120 break;
121
122 case 4:
123 coord[0] = 0;
124 coord[1] = +1;
125 break;
126
127 case 5:
128 coord[0] = -0;
129 coord[1] = -0;
130 break;
131
132 default:
133 break;
134 }
135 break;
136 }
137
138 return coord;
139 }
140
141 private enum NeighbourSystem
142 {
143 Moore,
144 VonNeumann
145 } ;
146
147 #endregion
148
149 #region ITerrainPaintableEffect Members
150
151 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration)
152 {
153 strength = TerrainUtil.MetersToSphericalStrength(strength);
154
155 int x;
156
157 for (x = 0; x < map.Width; x++)
158 {
159 int y;
160 for (y = 0; y < map.Height; y++)
161 {
162 if (!mask[x,y])
163 continue;
164
165 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
166
167 if (z > 0) // add in non-zero amount
168 {
169 const int NEIGHBOUR_ME = 4;
170 const int NEIGHBOUR_MAX = 9;
171
172 for (int j = 0; j < NEIGHBOUR_MAX; j++)
173 {
174 if (j != NEIGHBOUR_ME)
175 {
176 int[] coords = Neighbours(type, j);
177
178 coords[0] += x;
179 coords[1] += y;
180
181 if (coords[0] > map.Width - 1)
182 continue;
183 if (coords[1] > map.Height - 1)
184 continue;
185 if (coords[0] < 0)
186 continue;
187 if (coords[1] < 0)
188 continue;
189
190 double heightF = map[x, y];
191 double target = map[coords[0], coords[1]];
192
193 if (target > heightF + talus)
194 {
195 double calc = duration * ((target - heightF) - talus) * z;
196 heightF += calc;
197 target -= calc;
198 }
199
200 map[x, y] = heightF;
201 map[coords[0], coords[1]] = target;
202 }
203 }
204 }
205 }
206 }
207 }
208
209 #endregion
210 }
211}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/TerrainException.cs b/OpenSim/Region/Environment/Modules/World/Terrain/TerrainException.cs
deleted file mode 100644
index 2411de0..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/TerrainException.cs
+++ /dev/null
@@ -1,46 +0,0 @@
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 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 */
27
28using System;
29
30namespace OpenSim.Region.Environment.Modules.World.Terrain
31{
32 public class TerrainException : Exception
33 {
34 public TerrainException()
35 {
36 }
37
38 public TerrainException(string msg) : base(msg)
39 {
40 }
41
42 public TerrainException(string msg, Exception e) : base(msg, e)
43 {
44 }
45 }
46} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/TerrainModule.cs b/OpenSim/Region/Environment/Modules/World/Terrain/TerrainModule.cs
deleted file mode 100644
index bc601dc..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/TerrainModule.cs
+++ /dev/null
@@ -1,1001 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using OpenMetaverse;
33using log4net;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Region.Environment.Modules.Framework.InterfaceCommander;
39using OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders;
40using OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes;
41using OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes;
42
43namespace OpenSim.Region.Environment.Modules.World.Terrain
44{
45 public class TerrainModule : IRegionModule, ICommandableModule, ITerrainModule
46 {
47 #region StandardTerrainEffects enum
48
49 /// <summary>
50 /// A standard set of terrain brushes and effects recognised by viewers
51 /// </summary>
52 public enum StandardTerrainEffects : byte
53 {
54 Flatten = 0,
55 Raise = 1,
56 Lower = 2,
57 Smooth = 3,
58 Noise = 4,
59 Revert = 5,
60
61 // Extended brushes
62 Erode = 255,
63 Weather = 254,
64 Olsen = 253
65 }
66
67 #endregion
68
69 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
70
71 private readonly Commander m_commander = new Commander("terrain");
72
73 private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects =
74 new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>();
75
76 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
77
78 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
79 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
80
81 private ITerrainChannel m_channel;
82 private Dictionary<string, ITerrainEffect> m_plugineffects;
83 private ITerrainChannel m_revert;
84 private Scene m_scene;
85 private bool m_tainted;
86
87 #region ICommandableModule Members
88
89 public ICommander CommandInterface
90 {
91 get { return m_commander; }
92 }
93
94 #endregion
95
96 #region IRegionModule Members
97
98 /// <summary>
99 /// Creates and initialises a terrain module for a region
100 /// </summary>
101 /// <param name="scene">Region initialising</param>
102 /// <param name="config">Config for the region</param>
103 public void Initialise(Scene scene, IConfigSource config)
104 {
105 m_scene = scene;
106
107 // Install terrain module in the simulator
108 if (m_scene.Heightmap == null)
109 {
110 lock (m_scene)
111 {
112 m_channel = new TerrainChannel();
113 m_scene.Heightmap = m_channel;
114 m_revert = new TerrainChannel();
115 UpdateRevertMap();
116 }
117 }
118 else
119 {
120 m_channel = m_scene.Heightmap;
121 m_revert = new TerrainChannel();
122 UpdateRevertMap();
123 }
124
125 m_scene.RegisterModuleInterface<ITerrainModule>(this);
126 m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
127 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
128 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick;
129 }
130
131 /// <summary>
132 /// Enables terrain module when called
133 /// </summary>
134 public void PostInitialise()
135 {
136 InstallDefaultEffects();
137 InstallInterfaces();
138 LoadPlugins();
139 }
140
141 public void Close()
142 {
143 }
144
145 public string Name
146 {
147 get { return "TerrainModule"; }
148 }
149
150 public bool IsSharedModule
151 {
152 get { return false; }
153 }
154
155 #endregion
156
157 #region ITerrainModule Members
158
159 /// <summary>
160 /// Loads a terrain file from disk and installs it in the scene.
161 /// </summary>
162 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
163 public void LoadFromFile(string filename)
164 {
165 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
166 {
167 if (filename.EndsWith(loader.Key))
168 {
169 lock (m_scene)
170 {
171 try
172 {
173 ITerrainChannel channel = loader.Value.LoadFile(filename);
174 if (channel.Width != Constants.RegionSize || channel.Height != Constants.RegionSize)
175 {
176 // TerrainChannel expects a RegionSize x RegionSize map, currently
177 throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}",
178 Constants.RegionSize, Constants.RegionSize));
179 }
180 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height);
181 m_scene.Heightmap = channel;
182 m_channel = channel;
183 UpdateRevertMap();
184 }
185 catch (NotImplementedException)
186 {
187 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
188 " parser does not support file loading. (May be save only)");
189 throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value));
190 }
191 catch (FileNotFoundException)
192 {
193 m_log.Error(
194 "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)");
195 throw new TerrainException(
196 String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename));
197 }
198 catch (ArgumentException e)
199 {
200 m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message);
201 throw new TerrainException(
202 String.Format("Unable to load heightmap: {0}", e.Message));
203 }
204 }
205 CheckForTerrainUpdates();
206 m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
207 return;
208 }
209 }
210
211 m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader available for that format.");
212 throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename));
213 }
214
215 /// <summary>
216 /// Saves the current heightmap to a specified file.
217 /// </summary>
218 /// <param name="filename">The destination filename</param>
219 public void SaveToFile(string filename)
220 {
221 try
222 {
223 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
224 {
225 if (filename.EndsWith(loader.Key))
226 {
227 loader.Value.SaveFile(filename, m_channel);
228 return;
229 }
230 }
231 }
232 catch (NotImplementedException)
233 {
234 m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented.");
235 throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented"));
236 }
237 }
238
239 /// <summary>
240 /// Loads a terrain file from a stream and installs it in the scene.
241 /// </summary>
242 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
243 /// <param name="stream"></param>
244 public void LoadFromStream(string filename, Stream stream)
245 {
246 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
247 {
248 if (@filename.EndsWith(loader.Key))
249 {
250 lock (m_scene)
251 {
252 try
253 {
254 ITerrainChannel channel = loader.Value.LoadStream(stream);
255 m_scene.Heightmap = channel;
256 m_channel = channel;
257 UpdateRevertMap();
258 }
259 catch (NotImplementedException)
260 {
261 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
262 " parser does not support file loading. (May be save only)");
263 throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value));
264 }
265 }
266
267 CheckForTerrainUpdates();
268 m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
269 return;
270 }
271 }
272 m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader available for that format.");
273 throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename));
274 }
275
276 /// <summary>
277 /// Modify Land
278 /// </summary>
279 /// <param name="pos">Land-position (X,Y,0)</param>
280 /// <param name="size">The size of the brush (0=small, 1=medium, 2=large)</param>
281 /// <param name="action">0=LAND_LEVEL, 1=LAND_RAISE, 2=LAND_LOWER, 3=LAND_SMOOTH, 4=LAND_NOISE, 5=LAND_REVERT</param>
282 /// <param name="agentId">UUID of script-owner</param>
283 public void ModifyTerrain(UUID user, Vector3 pos, byte size, byte action, UUID agentId)
284 {
285 client_OnModifyTerrain(user, (float)pos.Z, (float)0.25, size, action, pos.Y, pos.X, pos.Y, pos.X, agentId);
286 }
287
288 /// <summary>
289 /// Saves the current heightmap to a specified stream.
290 /// </summary>
291 /// <param name="filename">The destination filename. Used here only to identify the image type</param>
292 /// <param name="stream"></param>
293 public void SaveToStream(string filename, Stream stream)
294 {
295 try
296 {
297 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
298 {
299 if (filename.EndsWith(loader.Key))
300 {
301 loader.Value.SaveStream(stream, m_channel);
302 return;
303 }
304 }
305 }
306 catch (NotImplementedException)
307 {
308 m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented.");
309 throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented"));
310 }
311 }
312
313 #region Plugin Loading Methods
314
315 private void LoadPlugins()
316 {
317 m_plugineffects = new Dictionary<string, ITerrainEffect>();
318 // Load the files in the Terrain/ dir
319 string[] files = Directory.GetFiles("Terrain");
320 foreach (string file in files)
321 {
322 m_log.Info("Loading effects in " + file);
323 try
324 {
325 Assembly library = Assembly.LoadFrom(file);
326 foreach (Type pluginType in library.GetTypes())
327 {
328 try
329 {
330 if (pluginType.IsAbstract || pluginType.IsNotPublic)
331 continue;
332
333 string typeName = pluginType.Name;
334
335 if (pluginType.GetInterface("ITerrainEffect", false) != null)
336 {
337 ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString()));
338
339 InstallPlugin(typeName, terEffect);
340 }
341 else if (pluginType.GetInterface("ITerrainLoader", false) != null)
342 {
343 ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString()));
344 m_loaders[terLoader.FileExtension] = terLoader;
345 m_log.Info("L ... " + typeName);
346 }
347 }
348 catch (AmbiguousMatchException)
349 {
350 }
351 }
352 }
353 catch (BadImageFormatException)
354 {
355 }
356 }
357 }
358
359 public void InstallPlugin(string pluginName, ITerrainEffect effect)
360 {
361 lock (m_plugineffects)
362 {
363 if (!m_plugineffects.ContainsKey(pluginName))
364 {
365 m_plugineffects.Add(pluginName, effect);
366 m_log.Info("E ... " + pluginName);
367 }
368 else
369 {
370 m_plugineffects[pluginName] = effect;
371 m_log.Warn("E ... " + pluginName + " (Replaced)");
372 }
373 }
374 }
375
376 #endregion
377
378 #endregion
379
380 /// <summary>
381 /// Installs into terrain module the standard suite of brushes
382 /// </summary>
383 private void InstallDefaultEffects()
384 {
385 // Draggable Paint Brush Effects
386 m_painteffects[StandardTerrainEffects.Raise] = new RaiseSphere();
387 m_painteffects[StandardTerrainEffects.Lower] = new LowerSphere();
388 m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere();
389 m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere();
390 m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere();
391 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_revert);
392 m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere();
393 m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere();
394 m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere();
395
396 // Area of effect selection effects
397 m_floodeffects[StandardTerrainEffects.Raise] = new RaiseArea();
398 m_floodeffects[StandardTerrainEffects.Lower] = new LowerArea();
399 m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea();
400 m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea();
401 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea();
402 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert);
403
404 // Filesystem load/save loaders
405 m_loaders[".r32"] = new RAW32();
406 m_loaders[".f32"] = m_loaders[".r32"];
407 m_loaders[".ter"] = new Terragen();
408 m_loaders[".raw"] = new LLRAW();
409 m_loaders[".jpg"] = new JPEG();
410 m_loaders[".jpeg"] = m_loaders[".jpg"];
411 m_loaders[".bmp"] = new BMP();
412 m_loaders[".png"] = new PNG();
413 m_loaders[".gif"] = new GIF();
414 m_loaders[".tif"] = new TIFF();
415 m_loaders[".tiff"] = m_loaders[".tif"];
416 }
417
418 /// <summary>
419 /// Saves the current state of the region into the revert map buffer.
420 /// </summary>
421 public void UpdateRevertMap()
422 {
423 int x;
424 for (x = 0; x < m_channel.Width; x++)
425 {
426 int y;
427 for (y = 0; y < m_channel.Height; y++)
428 {
429 m_revert[x, y] = m_channel[x, y];
430 }
431 }
432 }
433
434 /// <summary>
435 /// Loads a tile from a larger terrain file and installs it into the region.
436 /// </summary>
437 /// <param name="filename">The terrain file to load</param>
438 /// <param name="fileWidth">The width of the file in units</param>
439 /// <param name="fileHeight">The height of the file in units</param>
440 /// <param name="fileStartX">Where to begin our slice</param>
441 /// <param name="fileStartY">Where to begin our slice</param>
442 public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY)
443 {
444 int offsetX = (int) m_scene.RegionInfo.RegionLocX - fileStartX;
445 int offsetY = (int) m_scene.RegionInfo.RegionLocY - fileStartY;
446
447 if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight)
448 {
449 // this region is included in the tile request
450 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
451 {
452 if (filename.EndsWith(loader.Key))
453 {
454 lock (m_scene)
455 {
456 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
457 fileWidth, fileHeight,
458 (int) Constants.RegionSize,
459 (int) Constants.RegionSize);
460 m_scene.Heightmap = channel;
461 m_channel = channel;
462 UpdateRevertMap();
463 }
464 return;
465 }
466 }
467 }
468 }
469
470 /// <summary>
471 /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections
472 /// </summary>
473 private void EventManager_OnTerrainTick()
474 {
475 if (m_tainted)
476 {
477 m_tainted = false;
478 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
479 m_scene.SaveTerrain();
480
481 // Clients who look at the map will never see changes after they looked at the map, so i've commented this out.
482 //m_scene.CreateTerrainTexture(true);
483 }
484 }
485
486 /// <summary>
487 /// Processes commandline input. Do not call directly.
488 /// </summary>
489 /// <param name="args">Commandline arguments</param>
490 private void EventManager_OnPluginConsole(string[] args)
491 {
492 if (args[0] == "terrain")
493 {
494 if (args.Length == 1)
495 {
496 m_commander.ProcessConsoleCommand("help", new string[0]);
497 return;
498 }
499
500 string[] tmpArgs = new string[args.Length - 2];
501 int i;
502 for (i = 2; i < args.Length; i++)
503 tmpArgs[i - 2] = args[i];
504
505 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
506 }
507 }
508
509 /// <summary>
510 /// Installs terrain brush hook to IClientAPI
511 /// </summary>
512 /// <param name="client"></param>
513 private void EventManager_OnNewClient(IClientAPI client)
514 {
515 client.OnModifyTerrain += client_OnModifyTerrain;
516 client.OnBakeTerrain += client_OnBakeTerrain;
517 }
518
519 /// <summary>
520 /// Checks to see if the terrain has been modified since last check
521 /// but won't attempt to limit those changes to the limits specified in the estate settings
522 /// currently invoked by the command line operations in the region server only
523 /// </summary>
524 private void CheckForTerrainUpdates()
525 {
526 CheckForTerrainUpdates(false);
527 }
528
529 /// <summary>
530 /// Checks to see if the terrain has been modified since last check.
531 /// If it has been modified, every all the terrain patches are sent to the client.
532 /// If the call is asked to respect the estate settings for terrain_raise_limit and
533 /// terrain_lower_limit, it will clamp terrain updates between these values
534 /// currently invoked by client_OnModifyTerrain only and not the Commander interfaces
535 /// <param name="respectEstateSettings">should height map deltas be limited to the estate settings limits</param>
536 /// </summary>
537 private void CheckForTerrainUpdates(bool respectEstateSettings)
538 {
539 bool shouldTaint = false;
540 float[] serialised = m_channel.GetFloatsSerialised();
541 int x;
542 for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize)
543 {
544 int y;
545 for (y = 0; y < m_channel.Height; y += Constants.TerrainPatchSize)
546 {
547 if (m_channel.Tainted(x, y))
548 {
549 // if we should respect the estate settings then
550 // fixup and height deltas that don't respect them
551 if (respectEstateSettings && LimitChannelChanges(x, y))
552 {
553 // this has been vetoed, so update
554 // what we are going to send to the client
555 serialised = m_channel.GetFloatsSerialised();
556 }
557
558 SendToClients(serialised, x, y);
559 shouldTaint = true;
560 }
561 }
562 }
563 if (shouldTaint)
564 {
565 m_tainted = true;
566 }
567 }
568
569 /// <summary>
570 /// Checks to see height deltas in the tainted terrain patch at xStart ,yStart
571 /// are all within the current estate limits
572 /// <returns>true if changes were limited, false otherwise</returns>
573 /// </summary>
574 private bool LimitChannelChanges(int xStart, int yStart)
575 {
576 bool changesLimited = false;
577 double minDelta = m_scene.RegionInfo.RegionSettings.TerrainLowerLimit;
578 double maxDelta = m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
579
580 // loop through the height map for this patch and compare it against
581 // the revert map
582 for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++)
583 {
584 for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
585 {
586
587 double requestedHeight = m_channel[x, y];
588 double bakedHeight = m_revert[x, y];
589 double requestedDelta = requestedHeight - bakedHeight;
590
591 if (requestedDelta > maxDelta)
592 {
593 m_channel[x, y] = bakedHeight + maxDelta;
594 changesLimited = true;
595 }
596 else if (requestedDelta < minDelta)
597 {
598 m_channel[x, y] = bakedHeight + minDelta; //as lower is a -ve delta
599 changesLimited = true;
600 }
601 }
602 }
603
604 return changesLimited;
605 }
606
607 /// <summary>
608 /// Sends a copy of the current terrain to the scenes clients
609 /// </summary>
610 /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param>
611 /// <param name="x">The patch corner to send</param>
612 /// <param name="y">The patch corner to send</param>
613 private void SendToClients(float[] serialised, int x, int y)
614 {
615 m_scene.ForEachClient(
616 delegate(IClientAPI controller)
617 { controller.SendLayerData(
618 x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised);
619 }
620 );
621 }
622
623 private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action,
624 float north, float west, float south, float east, UUID agentId)
625 {
626 bool god = m_scene.Permissions.IsGod(user);
627 bool allowed = false;
628 if (north == south && east == west)
629 {
630 if (m_painteffects.ContainsKey((StandardTerrainEffects) action))
631 {
632 bool[,] allowMask = new bool[m_channel.Width,m_channel.Height];
633 allowMask.Initialize();
634 int n = size + 1;
635 if (n > 2)
636 n = 4;
637
638 int zx = (int) (west + 0.5);
639 int zy = (int) (north + 0.5);
640
641 int dx;
642 for (dx=-n; dx<=n; dx++)
643 {
644 int dy;
645 for (dy=-n; dy<=n; dy++)
646 {
647 int x = zx + dx;
648 int y = zy + dy;
649 if (x>=0 && y>=0 && x<m_channel.Width && y<m_channel.Height)
650 {
651 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0)))
652 {
653 allowMask[x, y] = true;
654 allowed = true;
655 }
656 }
657 }
658 }
659 if (allowed)
660 {
661 m_painteffects[(StandardTerrainEffects) action].PaintEffect(
662 m_channel, allowMask, west, south, height, size, seconds);
663
664 CheckForTerrainUpdates(!god); //revert changes outside estate limits
665 }
666 }
667 else
668 {
669 m_log.Debug("Unknown terrain brush type " + action);
670 }
671 }
672 else
673 {
674 if (m_floodeffects.ContainsKey((StandardTerrainEffects) action))
675 {
676 bool[,] fillArea = new bool[m_channel.Width,m_channel.Height];
677 fillArea.Initialize();
678
679 int x;
680 for (x = 0; x < m_channel.Width; x++)
681 {
682 int y;
683 for (y = 0; y < m_channel.Height; y++)
684 {
685 if (x < east && x > west)
686 {
687 if (y < north && y > south)
688 {
689 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0)))
690 {
691 fillArea[x, y] = true;
692 allowed = true;
693 }
694 }
695 }
696 }
697 }
698
699 if (allowed)
700 {
701 m_floodeffects[(StandardTerrainEffects) action].FloodEffect(
702 m_channel, fillArea, size);
703
704 CheckForTerrainUpdates(!god); //revert changes outside estate limits
705 }
706 }
707 else
708 {
709 m_log.Debug("Unknown terrain flood type " + action);
710 }
711 }
712 }
713
714 private void client_OnBakeTerrain(IClientAPI remoteClient)
715 {
716 // Not a good permissions check (see client_OnModifyTerrain above), need to check the entire area.
717 // for now check a point in the centre of the region
718
719 if (m_scene.Permissions.CanIssueEstateCommand(remoteClient.AgentId, true))
720 {
721 InterfaceBakeTerrain(null); //bake terrain does not use the passed in parameter
722 }
723 }
724
725 #region Console Commands
726
727 private void InterfaceLoadFile(Object[] args)
728 {
729 LoadFromFile((string) args[0]);
730 CheckForTerrainUpdates();
731 }
732
733 private void InterfaceLoadTileFile(Object[] args)
734 {
735 LoadFromFile((string) args[0],
736 (int) args[1],
737 (int) args[2],
738 (int) args[3],
739 (int) args[4]);
740 CheckForTerrainUpdates();
741 }
742
743 private void InterfaceSaveFile(Object[] args)
744 {
745 SaveToFile((string) args[0]);
746 }
747
748 private void InterfaceBakeTerrain(Object[] args)
749 {
750 UpdateRevertMap();
751 }
752
753 private void InterfaceRevertTerrain(Object[] args)
754 {
755 int x, y;
756 for (x = 0; x < m_channel.Width; x++)
757 for (y = 0; y < m_channel.Height; y++)
758 m_channel[x, y] = m_revert[x, y];
759
760 CheckForTerrainUpdates();
761 }
762
763 private void InterfaceFlipTerrain(Object[] args)
764 {
765 String direction = (String)args[0];
766
767 if (direction.ToLower().StartsWith("y"))
768 {
769 for (int x = 0; x < Constants.RegionSize; x++)
770 {
771 for (int y = 0; y < Constants.RegionSize / 2; y++)
772 {
773 double height = m_channel[x, y];
774 double flippedHeight = m_channel[x, (int)Constants.RegionSize - 1 - y];
775 m_channel[x, y] = flippedHeight;
776 m_channel[x, (int)Constants.RegionSize - 1 - y] = height;
777
778 }
779 }
780 }
781 else if (direction.ToLower().StartsWith("x"))
782 {
783 for (int y = 0; y < Constants.RegionSize; y++)
784 {
785 for (int x = 0; x < Constants.RegionSize / 2; x++)
786 {
787 double height = m_channel[x, y];
788 double flippedHeight = m_channel[(int)Constants.RegionSize - 1 - x, y];
789 m_channel[x, y] = flippedHeight;
790 m_channel[(int)Constants.RegionSize - 1 - x, y] = height;
791
792 }
793 }
794 }
795 else
796 {
797 m_log.Error("Unrecognised direction - need x or y");
798 }
799
800
801 CheckForTerrainUpdates();
802 }
803
804 private void InterfaceElevateTerrain(Object[] args)
805 {
806 int x, y;
807 for (x = 0; x < m_channel.Width; x++)
808 for (y = 0; y < m_channel.Height; y++)
809 m_channel[x, y] += (double) args[0];
810 CheckForTerrainUpdates();
811 }
812
813 private void InterfaceMultiplyTerrain(Object[] args)
814 {
815 int x, y;
816 for (x = 0; x < m_channel.Width; x++)
817 for (y = 0; y < m_channel.Height; y++)
818 m_channel[x, y] *= (double) args[0];
819 CheckForTerrainUpdates();
820 }
821
822 private void InterfaceLowerTerrain(Object[] args)
823 {
824 int x, y;
825 for (x = 0; x < m_channel.Width; x++)
826 for (y = 0; y < m_channel.Height; y++)
827 m_channel[x, y] -= (double) args[0];
828 CheckForTerrainUpdates();
829 }
830
831 private void InterfaceFillTerrain(Object[] args)
832 {
833 int x, y;
834
835 for (x = 0; x < m_channel.Width; x++)
836 for (y = 0; y < m_channel.Height; y++)
837 m_channel[x, y] = (double) args[0];
838 CheckForTerrainUpdates();
839 }
840
841 private void InterfaceShowDebugStats(Object[] args)
842 {
843 double max = Double.MinValue;
844 double min = double.MaxValue;
845 double sum = 0;
846
847 int x;
848 for (x = 0; x < m_channel.Width; x++)
849 {
850 int y;
851 for (y = 0; y < m_channel.Height; y++)
852 {
853 sum += m_channel[x, y];
854 if (max < m_channel[x, y])
855 max = m_channel[x, y];
856 if (min > m_channel[x, y])
857 min = m_channel[x, y];
858 }
859 }
860
861 double avg = sum / (m_channel.Height * m_channel.Width);
862
863 m_log.Info("Channel " + m_channel.Width + "x" + m_channel.Height);
864 m_log.Info("max/min/avg/sum: " + max + "/" + min + "/" + avg + "/" + sum);
865 }
866
867 private void InterfaceEnableExperimentalBrushes(Object[] args)
868 {
869 if ((bool) args[0])
870 {
871 m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere();
872 m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere();
873 m_painteffects[StandardTerrainEffects.Smooth] = new ErodeSphere();
874 }
875 else
876 {
877 InstallDefaultEffects();
878 }
879 }
880
881 private void InterfaceRunPluginEffect(Object[] args)
882 {
883 if ((string) args[0] == "list")
884 {
885 m_log.Info("List of loaded plugins");
886 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
887 {
888 m_log.Info(kvp.Key);
889 }
890 return;
891 }
892 if ((string) args[0] == "reload")
893 {
894 LoadPlugins();
895 return;
896 }
897 if (m_plugineffects.ContainsKey((string) args[0]))
898 {
899 m_plugineffects[(string) args[0]].RunEffect(m_channel);
900 CheckForTerrainUpdates();
901 }
902 else
903 {
904 m_log.Warn("No such plugin effect loaded.");
905 }
906 }
907
908 private void InstallInterfaces()
909 {
910 // Load / Save
911 string supportedFileExtensions = "";
912 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
913 supportedFileExtensions += " " + loader.Key + " (" + loader.Value + ")";
914
915 Command loadFromFileCommand =
916 new Command("load", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLoadFile, "Loads a terrain from a specified file.");
917 loadFromFileCommand.AddArgument("filename",
918 "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " +
919 supportedFileExtensions, "String");
920
921 Command saveToFileCommand =
922 new Command("save", CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceSaveFile, "Saves the current heightmap to a specified file.");
923 saveToFileCommand.AddArgument("filename",
924 "The destination filename for your heightmap, the file extension determines the format to save in. Supported extensions include: " +
925 supportedFileExtensions, "String");
926
927 Command loadFromTileCommand =
928 new Command("load-tile", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLoadTileFile, "Loads a terrain from a section of a larger file.");
929 loadFromTileCommand.AddArgument("filename",
930 "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " +
931 supportedFileExtensions, "String");
932 loadFromTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer");
933 loadFromTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer");
934 loadFromTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file",
935 "Integer");
936 loadFromTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file",
937 "Integer");
938
939 // Terrain adjustments
940 Command fillRegionCommand =
941 new Command("fill", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFillTerrain, "Fills the current heightmap with a specified value.");
942 fillRegionCommand.AddArgument("value", "The numeric value of the height you wish to set your region to.",
943 "Double");
944
945 Command elevateCommand =
946 new Command("elevate", CommandIntentions.COMMAND_HAZARDOUS, InterfaceElevateTerrain, "Raises the current heightmap by the specified amount.");
947 elevateCommand.AddArgument("amount", "The amount of height to add to the terrain in meters.", "Double");
948
949 Command lowerCommand =
950 new Command("lower", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLowerTerrain, "Lowers the current heightmap by the specified amount.");
951 lowerCommand.AddArgument("amount", "The amount of height to remove from the terrain in meters.", "Double");
952
953 Command multiplyCommand =
954 new Command("multiply", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMultiplyTerrain, "Multiplies the heightmap by the value specified.");
955 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double");
956
957 Command bakeRegionCommand =
958 new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions revert map.");
959 Command revertRegionCommand =
960 new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap.");
961
962 Command flipCommand =
963 new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis");
964 flipCommand.AddArgument("direction", "[x|y] the direction to flip the terrain in", "String");
965
966 // Debug
967 Command showDebugStatsCommand =
968 new Command("stats", CommandIntentions.COMMAND_STATISTICAL, InterfaceShowDebugStats,
969 "Shows some information about the regions heightmap for debugging purposes.");
970
971 Command experimentalBrushesCommand =
972 new Command("newbrushes", CommandIntentions.COMMAND_HAZARDOUS, InterfaceEnableExperimentalBrushes,
973 "Enables experimental brushes which replace the standard terrain brushes. WARNING: This is a debug setting and may be removed at any time.");
974 experimentalBrushesCommand.AddArgument("Enabled?", "true / false - Enable new brushes", "Boolean");
975
976 //Plugins
977 Command pluginRunCommand =
978 new Command("effect", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRunPluginEffect, "Runs a specified plugin effect");
979 pluginRunCommand.AddArgument("name", "The plugin effect you wish to run, or 'list' to see all plugins", "String");
980
981 m_commander.RegisterCommand("load", loadFromFileCommand);
982 m_commander.RegisterCommand("load-tile", loadFromTileCommand);
983 m_commander.RegisterCommand("save", saveToFileCommand);
984 m_commander.RegisterCommand("fill", fillRegionCommand);
985 m_commander.RegisterCommand("elevate", elevateCommand);
986 m_commander.RegisterCommand("lower", lowerCommand);
987 m_commander.RegisterCommand("multiply", multiplyCommand);
988 m_commander.RegisterCommand("bake", bakeRegionCommand);
989 m_commander.RegisterCommand("revert", revertRegionCommand);
990 m_commander.RegisterCommand("newbrushes", experimentalBrushesCommand);
991 m_commander.RegisterCommand("stats", showDebugStatsCommand);
992 m_commander.RegisterCommand("effect", pluginRunCommand);
993 m_commander.RegisterCommand("flip", flipCommand);
994
995 // Add this to our scene so scripts can call these functions
996 m_scene.RegisterModuleCommander(m_commander);
997 }
998
999 #endregion
1000 }
1001}
diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/Environment/Modules/World/Terrain/Tests/TerrainTest.cs
deleted file mode 100644
index 2acd5bc..0000000
--- a/OpenSim/Region/Environment/Modules/World/Terrain/Tests/TerrainTest.cs
+++ /dev/null
@@ -1,118 +0,0 @@
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 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 */
27
28using System;
29using NUnit.Framework;
30using OpenSim.Region.Framework.Scenes;
31using OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes;
32
33namespace OpenSim.Region.Environment.Modules.World.Terrain.Tests
34{
35 [TestFixture]
36 public class TerrainTest
37 {
38 [Test]
39 public void BrushTest()
40 {
41 bool[,] allowMask = new bool[256, 256];
42 int x;
43 int y;
44 for (x=0; x<128; x++)
45 {
46 for (y=0; y<256; y++)
47 {
48 allowMask[x,y] = true;
49 }
50 }
51
52 //
53 // Test RaiseSphere
54 //
55 TerrainChannel map = new TerrainChannel(256, 256);
56 ITerrainPaintableEffect effect = new RaiseSphere();
57
58 effect.PaintEffect(map, allowMask, 128.0, 128.0, -1.0, 2, 0.1);
59 Assert.That(map[127, 128] > 0.0, "Raise brush should raising value at this point (127,128).");
60 Assert.That(map[124, 128] > 0.0, "Raise brush should raising value at this point (124,128).");
61 Assert.That(map[123, 128] == 0.0, "Raise brush should not change value at this point (123,128).");
62 Assert.That(map[128, 128] == 0.0, "Raise brush should not change value at this point (128,128).");
63 Assert.That(map[0, 128] == 0.0, "Raise brush should not change value at this point (0,128).");
64
65 //
66 // Test LowerSphere
67 //
68 map = new TerrainChannel(256, 256);
69 for (x=0; x<map.Width; x++)
70 {
71 for (y=0; y<map.Height; y++)
72 {
73 map[x,y] = 1.0;
74 }
75 }
76 effect = new LowerSphere();
77
78 effect.PaintEffect(map, allowMask, 128.0, 128.0, -1.0, 2, 6.0);
79 Assert.That(map[127, 128] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
80 Assert.That(map[127, 128] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
81 Assert.That(map[124, 128] < 1.0, "Lower brush should lowering value at this point (124,128).");
82 Assert.That(map[123, 128] == 1.0, "Lower brush should not change value at this point (123,128).");
83 Assert.That(map[128, 128] == 1.0, "Lower brush should not change value at this point (128,128).");
84 Assert.That(map[0, 128] == 1.0, "Lower brush should not change value at this point (0,128).");
85 }
86
87 [Test]
88 public void TerrainChannelTest()
89 {
90 TerrainChannel x = new TerrainChannel(256, 256);
91 Assert.That(x[0, 0] == 0.0, "Terrain not initialising correctly.");
92
93 x[0, 0] = 1.0;
94 Assert.That(x[0, 0] == 1.0, "Terrain not setting values correctly.");
95
96 x[0, 0] = 0;
97 x[0, 0] += 5.0;
98 x[0, 0] -= 1.0;
99 Assert.That(x[0, 0] == 4.0, "Terrain addition/subtraction error.");
100
101 x[0, 0] = Math.PI;
102 double[,] doublesExport = x.GetDoubles();
103 Assert.That(doublesExport[0, 0] == Math.PI, "Export to double[,] array not working correctly.");
104
105 x[0, 0] = 1.0;
106 float[] floatsExport = x.GetFloatsSerialised();
107 Assert.That(floatsExport[0] == 1.0f, "Export to float[] not working correctly.");
108
109 x[0, 0] = 1.0;
110 Assert.That(x.Tainted(0, 0), "Terrain channel tainting not working correctly.");
111 Assert.That(!x.Tainted(0, 0), "Terrain channel tainting not working correctly.");
112
113 TerrainChannel y = x.Copy();
114 Assert.That(!ReferenceEquals(x, y), "Terrain copy not duplicating correctly.");
115 Assert.That(!ReferenceEquals(x.GetDoubles(), y.GetDoubles()), "Terrain array not duplicating correctly.");
116 }
117 }
118}
diff --git a/OpenSim/Region/Environment/Modules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/Environment/Modules/World/TreePopulator/TreePopulatorModule.cs
deleted file mode 100644
index 8a49540..0000000
--- a/OpenSim/Region/Environment/Modules/World/TreePopulator/TreePopulatorModule.cs
+++ /dev/null
@@ -1,304 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Timers;
32using OpenMetaverse;
33using log4net;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38
39namespace OpenSim.Region.Environment.Modules.World.TreePopulator
40{
41 /// <summary>
42 /// Version 2.0 - Very hacky compared to the original. Will fix original and release as 0.3 later.
43 /// </summary>
44 public class TreePopulatorModule : IRegionModule
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private Scene m_scene;
48
49 public double m_tree_density = 50.0; // Aim for this many per region
50 public double m_tree_updates = 1000.0; // MS between updates
51 private bool m_active_trees = false;
52 private List<UUID> m_trees;
53 Timer CalculateTrees;
54
55 #region IRegionModule Members
56
57 public void Initialise(Scene scene, IConfigSource config)
58 {
59 try
60 {
61 m_tree_density = config.Configs["Trees"].GetDouble("tree_density", m_tree_density);
62 m_active_trees = config.Configs["Trees"].GetBoolean("active_trees", m_active_trees);
63 }
64 catch (Exception)
65 {
66 }
67
68 m_trees = new List<UUID>();
69 m_scene = scene;
70
71 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
72
73 if (m_active_trees)
74 activeizeTreeze(true);
75
76 m_log.Debug("[TREES]: Initialised tree module");
77 }
78
79 public void PostInitialise()
80 {
81 }
82
83 public void Close()
84 {
85 }
86
87 public string Name
88 {
89 get { return "TreePopulatorModule"; }
90 }
91
92 public bool IsSharedModule
93 {
94 get { return false; }
95 }
96
97 #endregion
98
99 private void EventManager_OnPluginConsole(string[] args)
100 {
101 if (args.Length == 1)
102 {
103 if (args[0] == "tree")
104 {
105 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
106 if (uuid == UUID.Zero)
107 uuid = m_scene.RegionInfo.MasterAvatarAssignedUUID;
108 m_log.Debug("[TREES]: New tree planting");
109 CreateTree(uuid, new Vector3(128.0f, 128.0f, 0.0f));
110
111 }
112 }
113
114 if (args.Length == 2 || args.Length == 3)
115 {
116 if (args[1] == "active")
117 {
118 if (args.Length >= 3)
119 {
120 if (args[2] == "true" && !m_active_trees)
121 {
122 m_active_trees = true;
123 activeizeTreeze(m_active_trees);
124 m_log.Info("[TREES]: Activizing Trees");
125 }
126 if (args[2] == "false" && m_active_trees)
127 {
128 m_active_trees = false;
129 activeizeTreeze(m_active_trees);
130 m_log.Info("[TREES]: Trees no longer Active, for now...");
131 }
132 }
133 else
134 {
135 m_log.Info("[TREES]: When setting the tree module active via the console, you must specify true or false");
136 }
137 }
138 }
139
140 }
141
142 private void activeizeTreeze(bool activeYN)
143 {
144 if (activeYN)
145 {
146 CalculateTrees = new Timer(m_tree_updates);
147 CalculateTrees.Elapsed += CalculateTrees_Elapsed;
148 CalculateTrees.Start();
149 }
150 else
151 {
152 CalculateTrees.Stop();
153 }
154 }
155
156 private void growTrees()
157 {
158 foreach (UUID tree in m_trees)
159 {
160 if (m_scene.Entities.ContainsKey(tree))
161 {
162 SceneObjectPart s_tree = ((SceneObjectGroup) m_scene.Entities[tree]).RootPart;
163
164 // 100 seconds to grow 1m
165 s_tree.Scale += new Vector3(0.1f, 0.1f, 0.1f);
166 s_tree.SendFullUpdateToAllClients();
167 //s_tree.ScheduleTerseUpdate();
168 }
169 else
170 {
171 m_trees.Remove(tree);
172 }
173 }
174 }
175
176 private void seedTrees()
177 {
178 foreach (UUID tree in m_trees)
179 {
180 if (m_scene.Entities.ContainsKey(tree))
181 {
182 SceneObjectPart s_tree = ((SceneObjectGroup) m_scene.Entities[tree]).RootPart;
183
184 if (s_tree.Scale.X > 0.5)
185 {
186 if (Util.RandomClass.NextDouble() > 0.75)
187 {
188 SpawnChild(s_tree);
189 }
190 }
191 }
192 else
193 {
194 m_trees.Remove(tree);
195 }
196 }
197 }
198
199 private void killTrees()
200 {
201 foreach (UUID tree in m_trees)
202 {
203 double killLikelyhood = 0.0;
204
205 if (m_scene.Entities.ContainsKey(tree))
206 {
207 SceneObjectPart selectedTree = ((SceneObjectGroup) m_scene.Entities[tree]).RootPart;
208 double selectedTreeScale = Math.Sqrt(Math.Pow(selectedTree.Scale.X, 2) +
209 Math.Pow(selectedTree.Scale.Y, 2) +
210 Math.Pow(selectedTree.Scale.Z, 2));
211
212 foreach (UUID picktree in m_trees)
213 {
214 if (picktree != tree)
215 {
216 SceneObjectPart pickedTree = ((SceneObjectGroup) m_scene.Entities[picktree]).RootPart;
217
218 double pickedTreeScale = Math.Sqrt(Math.Pow(pickedTree.Scale.X, 2) +
219 Math.Pow(pickedTree.Scale.Y, 2) +
220 Math.Pow(pickedTree.Scale.Z, 2));
221
222 double pickedTreeDistance = Math.Sqrt(Math.Pow(Math.Abs(pickedTree.AbsolutePosition.X - selectedTree.AbsolutePosition.X), 2) +
223 Math.Pow(Math.Abs(pickedTree.AbsolutePosition.Y - selectedTree.AbsolutePosition.Y), 2) +
224 Math.Pow(Math.Abs(pickedTree.AbsolutePosition.Z - selectedTree.AbsolutePosition.Z), 2));
225
226 killLikelyhood += (selectedTreeScale / (pickedTreeScale * pickedTreeDistance)) * 0.1;
227 }
228 }
229
230 if (Util.RandomClass.NextDouble() < killLikelyhood)
231 {
232 m_scene.DeleteSceneObject(selectedTree.ParentGroup, false);
233 m_trees.Remove(selectedTree.ParentGroup.UUID);
234
235 m_scene.ForEachClient(delegate(IClientAPI controller)
236 {
237 controller.SendKillObject(m_scene.RegionInfo.RegionHandle,
238 selectedTree.LocalId);
239 });
240
241 break;
242 }
243 selectedTree.SetText(killLikelyhood.ToString(), new Vector3(1.0f, 1.0f, 1.0f), 1.0);
244 }
245 else
246 {
247 m_trees.Remove(tree);
248 }
249 }
250 }
251
252 private void SpawnChild(SceneObjectPart s_tree)
253 {
254 Vector3 position = new Vector3();
255
256 position.X = s_tree.AbsolutePosition.X + (1 * (-1 * Util.RandomClass.Next(1)));
257 if (position.X > 255)
258 position.X = 255;
259 if (position.X < 0)
260 position.X = 0;
261 position.Y = s_tree.AbsolutePosition.Y + (1 * (-1 * Util.RandomClass.Next(1)));
262 if (position.Y > 255)
263 position.Y = 255;
264 if (position.Y < 0)
265 position.Y = 0;
266
267 double randX = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3);
268 double randY = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3);
269
270 position.X += (float) randX;
271 position.Y += (float) randY;
272
273 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
274 if (uuid == UUID.Zero)
275 uuid = m_scene.RegionInfo.MasterAvatarAssignedUUID;
276
277 CreateTree(uuid, position);
278 }
279
280 private void CreateTree(UUID uuid, Vector3 position)
281 {
282 position.Z = (float) m_scene.Heightmap[(int) position.X, (int) position.Y];
283
284 IVegetationModule module = m_scene.RequestModuleInterface<IVegetationModule>();
285
286 if (null == module)
287 return;
288
289 SceneObjectGroup tree
290 = module.AddTree(
291 uuid, UUID.Zero, new Vector3(0.1f, 0.1f, 0.1f), Quaternion.Identity, position, Tree.Cypress1, false);
292
293 m_trees.Add(tree.UUID);
294 tree.SendGroupFullUpdate();
295 }
296
297 private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e)
298 {
299 growTrees();
300 seedTrees();
301 killTrees();
302 }
303 }
304}
diff --git a/OpenSim/Region/Environment/Modules/World/Vegetation/VegetationModule.cs b/OpenSim/Region/Environment/Modules/World/Vegetation/VegetationModule.cs
deleted file mode 100644
index 4c4ca0d..0000000
--- a/OpenSim/Region/Environment/Modules/World/Vegetation/VegetationModule.cs
+++ /dev/null
@@ -1,118 +0,0 @@
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 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 */
27
28using System;
29using System.Reflection;
30using log4net;
31using Nini.Config;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications;
35using OpenSim.Framework.Communications.Cache;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38
39namespace OpenSim.Region.Environment.Modules.Avatar.Vegetation
40{
41 public class VegetationModule : IRegionModule, IVegetationModule
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 protected Scene m_scene;
46
47 protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.Grass, PCode.NewTree, PCode.Tree };
48 public PCode[] CreationCapabilities { get { return creationCapabilities; } }
49
50 public void Initialise(Scene scene, IConfigSource source)
51 {
52 m_scene = scene;
53 m_scene.RegisterModuleInterface<IVegetationModule>(this);
54 }
55
56 public void PostInitialise() {}
57 public void Close() {}
58 public string Name { get { return "Vegetation Module"; } }
59 public bool IsSharedModule { get { return false; } }
60
61 public SceneObjectGroup AddTree(
62 UUID uuid, UUID groupID, Vector3 scale, Quaternion rotation, Vector3 position, Tree treeType, bool newTree)
63 {
64 PrimitiveBaseShape treeShape = new PrimitiveBaseShape();
65 treeShape.PathCurve = 16;
66 treeShape.PathEnd = 49900;
67 treeShape.PCode = newTree ? (byte)PCode.NewTree : (byte)PCode.Tree;
68 treeShape.Scale = scale;
69 treeShape.State = (byte)treeType;
70
71 return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape);
72 }
73
74 public SceneObjectGroup CreateEntity(
75 UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
76 {
77 if (Array.IndexOf(creationCapabilities, (PCode)shape.PCode) < 0)
78 {
79 m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name);
80 return null;
81 }
82
83 SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape);
84 SceneObjectPart rootPart = sceneObject.GetChildPart(sceneObject.UUID);
85
86 // if grass or tree, make phantom
87 //rootPart.TrimPermissions();
88 rootPart.AddFlag(PrimFlags.Phantom);
89 if (rootPart.Shape.PCode != (byte)PCode.Grass)
90 AdaptTree(ref shape);
91
92 m_scene.AddNewSceneObject(sceneObject, true);
93 sceneObject.SetGroup(groupID, null);
94
95 return sceneObject;
96 }
97
98 protected void AdaptTree(ref PrimitiveBaseShape tree)
99 {
100 // Tree size has to be adapted depending on its type
101 switch ((Tree)tree.State)
102 {
103 case Tree.Cypress1:
104 case Tree.Cypress2:
105 tree.Scale = new Vector3(4, 4, 10);
106 break;
107
108 // case... other tree types
109 // tree.Scale = new Vector3(?, ?, ?);
110 // break;
111
112 default:
113 tree.Scale = new Vector3(4, 4, 4);
114 break;
115 }
116 }
117 }
118}
diff --git a/OpenSim/Region/Environment/Modules/World/Wind/WindModule.cs b/OpenSim/Region/Environment/Modules/World/Wind/WindModule.cs
deleted file mode 100644
index 8e54fd9..0000000
--- a/OpenSim/Region/Environment/Modules/World/Wind/WindModule.cs
+++ /dev/null
@@ -1,207 +0,0 @@
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 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 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using Nini.Config;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes;
35
36namespace OpenSim.Region.Environment.Modules
37{
38 public class WindModule : IWindModule
39 {
40// private static readonly log4net.ILog m_log
41// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
42
43 private int m_frame = 0;
44 private int m_frame_mod = 150;
45 private Random rndnums = new Random(System.Environment.TickCount);
46 private Scene m_scene = null;
47 private bool ready = false;
48 private Vector2[] windSpeeds = new Vector2[16 * 16];
49 private Dictionary<UUID, ulong> m_rootAgents = new Dictionary<UUID, ulong>();
50
51 public void Initialise(Scene scene, IConfigSource config)
52 {
53 m_scene = scene;
54 m_frame = 0;
55
56 scene.EventManager.OnFrame += WindUpdate;
57 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
58 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
59 scene.EventManager.OnClientClosed += ClientLoggedOut;
60 scene.RegisterModuleInterface<IWindModule>(this);
61
62 GenWindPos();
63
64 ready = true;
65 }
66
67 public void PostInitialise()
68 {
69 }
70
71 public void Close()
72 {
73 ready = false;
74 // Remove our hooks
75 m_scene.EventManager.OnFrame -= WindUpdate;
76 // m_scene.EventManager.OnNewClient -= SunToClient;
77 m_scene.EventManager.OnMakeChildAgent -= MakeChildAgent;
78 m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel;
79 m_scene.EventManager.OnClientClosed -= ClientLoggedOut;
80 }
81
82 public string Name
83 {
84 get { return "WindModule"; }
85 }
86
87 public bool IsSharedModule
88 {
89 get { return false; }
90 }
91
92 public Vector2[] WindSpeeds
93 {
94 get { return windSpeeds; }
95 }
96
97 public void WindToClient(IClientAPI client)
98 {
99 if (ready)
100 {
101 //if (!sunFixed)
102 //GenWindPos(); // Generate shared values once
103 client.SendWindData(windSpeeds);
104 }
105 }
106
107 public void WindUpdate()
108 {
109 if (((m_frame++ % m_frame_mod) != 0) || !ready)
110 {
111 return;
112 }
113 //m_log.Debug("[WIND]:Regenerating...");
114 GenWindPos(); // Generate shared values once
115
116 //int spotxp = 0;
117 //int spotyp = 0;
118 //int spotxm = 0;
119 //int spotym = 0;
120 List<ScenePresence> avatars = m_scene.GetAvatars();
121 foreach (ScenePresence avatar in avatars)
122 {
123 if (!avatar.IsChildAgent)
124 {
125 avatar.ControllingClient.SendWindData(windSpeeds);
126 }
127 }
128
129 // set estate settings for region access to sun position
130 //m_scene.RegionInfo.RegionSettings.SunVector = Position;
131 //m_scene.RegionInfo.EstateSettings.sunHour = GetLindenEstateHourFromCurrentTime();
132 }
133
134 public void ForceWindUpdateToAllClients()
135 {
136 GenWindPos(); // Generate shared values once
137
138 List<ScenePresence> avatars = m_scene.GetAvatars();
139 foreach (ScenePresence avatar in avatars)
140 {
141 if (!avatar.IsChildAgent)
142 avatar.ControllingClient.SendWindData(windSpeeds);
143 }
144
145 // set estate settings for region access to sun position
146 //m_scene.RegionInfo.RegionSettings.SunVector = Position;
147 //m_scene.RegionInfo.RegionSettings.SunPosition = GetLindenEstateHourFromCurrentTime();
148 }
149 /// <summary>
150 /// Calculate the sun's orbital position and its velocity.
151 /// </summary>
152
153 private void GenWindPos()
154 {
155 for (int y = 0; y < 16; y++)
156 {
157 for (int x = 0; x < 16; x++)
158 {
159 windSpeeds[y * 16 + x].X = (float)(rndnums.NextDouble() * 2d - 1d);
160 windSpeeds[y * 16 + x].Y = (float)(rndnums.NextDouble() * 2d - 1d);
161 }
162 }
163 }
164
165 private void ClientLoggedOut(UUID AgentId)
166 {
167 lock (m_rootAgents)
168 {
169 if (m_rootAgents.ContainsKey(AgentId))
170 {
171 m_rootAgents.Remove(AgentId);
172 }
173 }
174 }
175
176 private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID)
177 {
178 lock (m_rootAgents)
179 {
180 if (m_rootAgents.ContainsKey(avatar.UUID))
181 {
182 m_rootAgents[avatar.UUID] = avatar.RegionHandle;
183 }
184 else
185 {
186 m_rootAgents.Add(avatar.UUID, avatar.RegionHandle);
187 WindToClient(avatar.ControllingClient);
188 }
189 }
190 //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString());
191 }
192
193 private void MakeChildAgent(ScenePresence avatar)
194 {
195 lock (m_rootAgents)
196 {
197 if (m_rootAgents.ContainsKey(avatar.UUID))
198 {
199 if (m_rootAgents[avatar.UUID] == avatar.RegionHandle)
200 {
201 m_rootAgents.Remove(avatar.UUID);
202 }
203 }
204 }
205 }
206 }
207}
diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/IMapTileTerrainRenderer.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/IMapTileTerrainRenderer.cs
deleted file mode 100644
index cb0ac8c..0000000
--- a/OpenSim/Region/Environment/Modules/World/WorldMap/IMapTileTerrainRenderer.cs
+++ /dev/null
@@ -1,39 +0,0 @@
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 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 */
27
28using System.Drawing;
29using OpenSim.Region.Framework.Scenes;
30using Nini.Config;
31
32namespace OpenSim.Region.Environment
33{
34 public interface IMapTileTerrainRenderer
35 {
36 void Initialise(Scene scene, IConfigSource config);
37 void TerrainToBitmap(Bitmap mapbmp);
38 }
39}
diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/MapImageModule.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/MapImageModule.cs
deleted file mode 100644
index a806c7d..0000000
--- a/OpenSim/Region/Environment/Modules/World/WorldMap/MapImageModule.cs
+++ /dev/null
@@ -1,586 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Drawing;
32using System.Drawing.Drawing2D;
33using System.Drawing.Imaging;
34using System.Reflection;
35using Nini.Config;
36using OpenMetaverse.Imaging;
37using log4net;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenMetaverse;
41
42namespace OpenSim.Region.Environment.Modules.World.WorldMap
43{
44 public enum DrawRoutine
45 {
46 Rectangle,
47 Polygon,
48 Ellipse
49 }
50
51 public struct face
52 {
53 public Point[] pts;
54 }
55
56 public struct DrawStruct
57 {
58 public DrawRoutine dr;
59 public Rectangle rect;
60 public SolidBrush brush;
61 public face[] trns;
62 }
63
64 public class MapImageModule : IMapImageGenerator, IRegionModule
65 {
66 private static readonly ILog m_log =
67 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
68
69 private Scene m_scene;
70 private IConfigSource m_config;
71 private IMapTileTerrainRenderer terrainRenderer;
72
73 #region IMapImageGenerator Members
74
75 public byte[] WriteJpeg2000Image(string gradientmap)
76 {
77 byte[] imageData = null;
78
79 bool drawPrimVolume = true;
80 bool textureTerrain = true;
81
82 try
83 {
84 IConfig startupConfig = m_config.Configs["Startup"];
85 drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", drawPrimVolume);
86 textureTerrain = startupConfig.GetBoolean("TextureOnMapTile", textureTerrain);
87 }
88 catch
89 {
90 m_log.Warn("[MAPTILE]: Failed to load StartupConfig");
91 }
92
93 if (textureTerrain)
94 {
95 terrainRenderer = new TexturedMapTileRenderer();
96 }
97 else
98 {
99 terrainRenderer = new ShadedMapTileRenderer();
100 }
101 terrainRenderer.Initialise(m_scene, m_config);
102
103 Bitmap mapbmp = new Bitmap(256, 256);
104 //long t = System.Environment.TickCount;
105 //for (int i = 0; i < 10; ++i) {
106 terrainRenderer.TerrainToBitmap(mapbmp);
107 //}
108 //t = System.Environment.TickCount - t;
109 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t);
110
111
112 if (drawPrimVolume)
113 {
114 DrawObjectVolume(m_scene, mapbmp);
115 }
116
117 try
118 {
119 imageData = OpenJPEG.EncodeFromImage(mapbmp, true);
120 }
121 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke
122 {
123 Console.WriteLine("Failed generating terrain map: " + e);
124 }
125
126 return imageData;
127 }
128
129 #endregion
130
131 #region IRegionModule Members
132
133 public void Initialise(Scene scene, IConfigSource source)
134 {
135 m_scene = scene;
136 m_config = source;
137
138 IConfig startupConfig = m_config.Configs["Startup"];
139 if (startupConfig.GetString("MapImageModule", "MapImageModule") !=
140 "MapImageModule")
141 return;
142
143 m_scene.RegisterModuleInterface<IMapImageGenerator>(this);
144 }
145
146 public void PostInitialise()
147 {
148 }
149
150 public void Close()
151 {
152 }
153
154 public string Name
155 {
156 get { return "MapImageModule"; }
157 }
158
159 public bool IsSharedModule
160 {
161 get { return false; }
162 }
163
164 #endregion
165
166// TODO: unused:
167// private void ShadeBuildings(Bitmap map)
168// {
169// lock (map)
170// {
171// lock (m_scene.Entities)
172// {
173// foreach (EntityBase entity in m_scene.Entities.Values)
174// {
175// if (entity is SceneObjectGroup)
176// {
177// SceneObjectGroup sog = (SceneObjectGroup) entity;
178//
179// foreach (SceneObjectPart primitive in sog.Children.Values)
180// {
181// int x = (int) (primitive.AbsolutePosition.X - (primitive.Scale.X / 2));
182// int y = (int) (primitive.AbsolutePosition.Y - (primitive.Scale.Y / 2));
183// int w = (int) primitive.Scale.X;
184// int h = (int) primitive.Scale.Y;
185//
186// int dx;
187// for (dx = x; dx < x + w; dx++)
188// {
189// int dy;
190// for (dy = y; dy < y + h; dy++)
191// {
192// if (x < 0 || y < 0)
193// continue;
194// if (x >= map.Width || y >= map.Height)
195// continue;
196//
197// map.SetPixel(dx, dy, Color.DarkGray);
198// }
199// }
200// }
201// }
202// }
203// }
204// }
205// }
206
207 private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp)
208 {
209 int tc = 0;
210 double[,] hm = whichScene.Heightmap.GetDoubles();
211 tc = System.Environment.TickCount;
212 m_log.Info("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
213 List<EntityBase> objs = whichScene.GetEntities();
214 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
215 //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
216 List<float> z_sortheights = new List<float>();
217 List<uint> z_localIDs = new List<uint>();
218
219 lock (objs)
220 {
221 foreach (EntityBase obj in objs)
222 {
223 // Only draw the contents of SceneObjectGroup
224 if (obj is SceneObjectGroup)
225 {
226 SceneObjectGroup mapdot = (SceneObjectGroup)obj;
227 Color mapdotspot = Color.Gray; // Default color when prim color is white
228 // Loop over prim in group
229 foreach (SceneObjectPart part in mapdot.Children.Values)
230 {
231 if (part == null)
232 continue;
233
234 // Draw if the object is at least 1 meter wide in any direction
235 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f)
236 {
237 // Try to get the RGBA of the default texture entry..
238 //
239 try
240 {
241 // get the null checks out of the way
242 // skip the ones that break
243 if (part == null)
244 continue;
245
246 if (part.Shape == null)
247 continue;
248
249 if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass)
250 continue; // eliminates trees from this since we don't really have a good tree representation
251 // if you want tree blocks on the map comment the above line and uncomment the below line
252 //mapdotspot = Color.PaleGreen;
253
254 if (part.Shape.Textures == null)
255 continue;
256
257 if (part.Shape.Textures.DefaultTexture == null)
258 continue;
259
260 Color4 texcolor = part.Shape.Textures.DefaultTexture.RGBA;
261
262 // Not sure why some of these are null, oh well.
263
264 int colorr = 255 - (int)(texcolor.R * 255f);
265 int colorg = 255 - (int)(texcolor.G * 255f);
266 int colorb = 255 - (int)(texcolor.B * 255f);
267
268 if (!(colorr == 255 && colorg == 255 && colorb == 255))
269 {
270 //Try to set the map spot color
271 try
272 {
273 // If the color gets goofy somehow, skip it *shakes fist at Color4
274 mapdotspot = Color.FromArgb(colorr, colorg, colorb);
275 }
276 catch (ArgumentException)
277 {
278 }
279 }
280 }
281 catch (IndexOutOfRangeException)
282 {
283 // Windows Array
284 }
285 catch (ArgumentOutOfRangeException)
286 {
287 // Mono Array
288 }
289
290 Vector3 pos = part.GetWorldPosition();
291
292 // skip prim outside of retion
293 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
294 continue;
295
296 // skip prim in non-finite position
297 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
298 Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
299 continue;
300
301 // Figure out if object is under 256m above the height of the terrain
302 bool isBelow256AboveTerrain = false;
303
304 try
305 {
306 isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
307 }
308 catch (Exception)
309 {
310 }
311
312 if (isBelow256AboveTerrain)
313 {
314 // Translate scale by rotation so scale is represented properly when object is rotated
315 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
316 Vector3 scale = new Vector3();
317 Vector3 tScale = new Vector3();
318 Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
319
320 Quaternion llrot = part.GetWorldRotation();
321 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
322 scale = lscale * rot;
323
324 // negative scales don't work in this situation
325 scale.X = Math.Abs(scale.X);
326 scale.Y = Math.Abs(scale.Y);
327 scale.Z = Math.Abs(scale.Z);
328
329 // This scaling isn't very accurate and doesn't take into account the face rotation :P
330 int mapdrawstartX = (int)(pos.X - scale.X);
331 int mapdrawstartY = (int)(pos.Y - scale.Y);
332 int mapdrawendX = (int)(pos.X + scale.X);
333 int mapdrawendY = (int)(pos.Y + scale.Y);
334
335 // If object is beyond the edge of the map, don't draw it to avoid errors
336 if (mapdrawstartX < 0 || mapdrawstartX > 255 || mapdrawendX < 0 || mapdrawendX > 255
337 || mapdrawstartY < 0 || mapdrawstartY > 255 || mapdrawendY < 0
338 || mapdrawendY > 255)
339 continue;
340
341#region obb face reconstruction part duex
342 Vector3[] vertexes = new Vector3[8];
343
344 // float[] distance = new float[6];
345 Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
346 Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
347 Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
348 Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
349
350 tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
351 scale = ((tScale * rot));
352 vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
353 // vertexes[0].x = pos.X + vertexes[0].x;
354 //vertexes[0].y = pos.Y + vertexes[0].y;
355 //vertexes[0].z = pos.Z + vertexes[0].z;
356
357 FaceA[0] = vertexes[0];
358 FaceB[3] = vertexes[0];
359 FaceA[4] = vertexes[0];
360
361 tScale = lscale;
362 scale = ((tScale * rot));
363 vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
364
365 // vertexes[1].x = pos.X + vertexes[1].x;
366 // vertexes[1].y = pos.Y + vertexes[1].y;
367 //vertexes[1].z = pos.Z + vertexes[1].z;
368
369 FaceB[0] = vertexes[1];
370 FaceA[1] = vertexes[1];
371 FaceC[4] = vertexes[1];
372
373 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
374 scale = ((tScale * rot));
375
376 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
377
378 //vertexes[2].x = pos.X + vertexes[2].x;
379 //vertexes[2].y = pos.Y + vertexes[2].y;
380 //vertexes[2].z = pos.Z + vertexes[2].z;
381
382 FaceC[0] = vertexes[2];
383 FaceD[3] = vertexes[2];
384 FaceC[5] = vertexes[2];
385
386 tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
387 scale = ((tScale * rot));
388 vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
389
390 //vertexes[3].x = pos.X + vertexes[3].x;
391 // vertexes[3].y = pos.Y + vertexes[3].y;
392 // vertexes[3].z = pos.Z + vertexes[3].z;
393
394 FaceD[0] = vertexes[3];
395 FaceC[1] = vertexes[3];
396 FaceA[5] = vertexes[3];
397
398 tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
399 scale = ((tScale * rot));
400 vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
401
402 // vertexes[4].x = pos.X + vertexes[4].x;
403 // vertexes[4].y = pos.Y + vertexes[4].y;
404 // vertexes[4].z = pos.Z + vertexes[4].z;
405
406 FaceB[1] = vertexes[4];
407 FaceA[2] = vertexes[4];
408 FaceD[4] = vertexes[4];
409
410 tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
411 scale = ((tScale * rot));
412 vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
413
414 // vertexes[5].x = pos.X + vertexes[5].x;
415 // vertexes[5].y = pos.Y + vertexes[5].y;
416 // vertexes[5].z = pos.Z + vertexes[5].z;
417
418 FaceD[1] = vertexes[5];
419 FaceC[2] = vertexes[5];
420 FaceB[5] = vertexes[5];
421
422 tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z);
423 scale = ((tScale * rot));
424 vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
425
426 // vertexes[6].x = pos.X + vertexes[6].x;
427 // vertexes[6].y = pos.Y + vertexes[6].y;
428 // vertexes[6].z = pos.Z + vertexes[6].z;
429
430 FaceB[2] = vertexes[6];
431 FaceA[3] = vertexes[6];
432 FaceB[4] = vertexes[6];
433
434 tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z);
435 scale = ((tScale * rot));
436 vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
437
438 // vertexes[7].x = pos.X + vertexes[7].x;
439 // vertexes[7].y = pos.Y + vertexes[7].y;
440 // vertexes[7].z = pos.Z + vertexes[7].z;
441
442 FaceD[2] = vertexes[7];
443 FaceC[3] = vertexes[7];
444 FaceD[5] = vertexes[7];
445#endregion
446
447 //int wy = 0;
448
449 //bool breakYN = false; // If we run into an error drawing, break out of the
450 // loop so we don't lag to death on error handling
451 DrawStruct ds = new DrawStruct();
452 ds.brush = new SolidBrush(mapdotspot);
453 //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY);
454
455 ds.trns = new face[FaceA.Length];
456
457 for (int i = 0; i < FaceA.Length; i++)
458 {
459 Point[] working = new Point[5];
460 working[0] = project(FaceA[i], axPos);
461 working[1] = project(FaceB[i], axPos);
462 working[2] = project(FaceD[i], axPos);
463 working[3] = project(FaceC[i], axPos);
464 working[4] = project(FaceA[i], axPos);
465
466 face workingface = new face();
467 workingface.pts = working;
468
469 ds.trns[i] = workingface;
470 }
471
472 z_sort.Add(part.LocalId, ds);
473 z_localIDs.Add(part.LocalId);
474 z_sortheights.Add(pos.Z);
475
476 //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++)
477 //{
478 //for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
479 //{
480 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy);
481 //try
482 //{
483 // Remember, flip the y!
484 // mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
485 //}
486 //catch (ArgumentException)
487 //{
488 // breakYN = true;
489 //}
490
491 //if (breakYN)
492 // break;
493 //}
494
495 //if (breakYN)
496 // break;
497 //}
498 } // Object is within 256m Z of terrain
499 } // object is at least a meter wide
500 } // loop over group children
501 } // entitybase is sceneobject group
502 } // foreach loop over entities
503
504 float[] sortedZHeights = z_sortheights.ToArray();
505 uint[] sortedlocalIds = z_localIDs.ToArray();
506
507 // Sort prim by Z position
508 Array.Sort(sortedZHeights, sortedlocalIds);
509
510 Graphics g = Graphics.FromImage(mapbmp);
511
512 for (int s = 0; s < sortedZHeights.Length; s++)
513 {
514 if (z_sort.ContainsKey(sortedlocalIds[s]))
515 {
516 DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]];
517 for (int r = 0; r < rectDrawStruct.trns.Length; r++ )
518 {
519 g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts);
520 }
521 //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect);
522 }
523 }
524
525 g.Dispose();
526 } // lock entities objs
527
528 m_log.Info("[MAPTILE]: Generating Maptile Step 2: Done in " + (System.Environment.TickCount - tc) + " ms");
529 return mapbmp;
530 }
531
532 private Point project(Vector3 point3d, Vector3 originpos)
533 {
534 Point returnpt = new Point();
535 //originpos = point3d;
536 //int d = (int)(256f / 1.5f);
537
538 //Vector3 topos = new Vector3(0, 0, 0);
539 // float z = -point3d.z - topos.z;
540
541 returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d);
542 returnpt.Y = (int)(255 - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d)));
543
544 return returnpt;
545 }
546
547// TODO: unused:
548// #region Deprecated Maptile Generation. Adam may update this
549// private Bitmap TerrainToBitmap(string gradientmap)
550// {
551// Bitmap gradientmapLd = new Bitmap(gradientmap);
552//
553// int pallete = gradientmapLd.Height;
554//
555// Bitmap bmp = new Bitmap(m_scene.Heightmap.Width, m_scene.Heightmap.Height);
556// Color[] colours = new Color[pallete];
557//
558// for (int i = 0; i < pallete; i++)
559// {
560// colours[i] = gradientmapLd.GetPixel(0, i);
561// }
562//
563// lock (m_scene.Heightmap)
564// {
565// ITerrainChannel copy = m_scene.Heightmap;
566// for (int y = 0; y < copy.Height; y++)
567// {
568// for (int x = 0; x < copy.Width; x++)
569// {
570// // 512 is the largest possible height before colours clamp
571// int colorindex = (int) (Math.Max(Math.Min(1.0, copy[x, y] / 512.0), 0.0) * (pallete - 1));
572//
573// // Handle error conditions
574// if (colorindex > pallete - 1 || colorindex < 0)
575// bmp.SetPixel(x, copy.Height - y - 1, Color.Red);
576// else
577// bmp.SetPixel(x, copy.Height - y - 1, colours[colorindex]);
578// }
579// }
580// ShadeBuildings(bmp);
581// return bmp;
582// }
583// }
584// #endregion
585 }
586}
diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/MapSearchModule.cs
deleted file mode 100644
index 43ed1e4..0000000
--- a/OpenSim/Region/Environment/Modules/World/WorldMap/MapSearchModule.cs
+++ /dev/null
@@ -1,172 +0,0 @@
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 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 System;
28using System.Reflection;
29using System.Collections.Generic;
30using System.Net;
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Region.Framework.Scenes.Hypergrid;
35using OpenMetaverse;
36using log4net;
37using Nini.Config;
38
39namespace OpenSim.Region.Environment.Modules.World.WorldMap
40{
41 public class MapSearchModule : IRegionModule
42 {
43 private static readonly ILog m_log =
44 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 Scene m_scene = null; // only need one for communication with GridService
47 List<Scene> m_scenes = new List<Scene>();
48
49 #region IRegionModule Members
50 public void Initialise(Scene scene, IConfigSource source)
51 {
52 if (m_scene == null)
53 {
54 m_scene = scene;
55 }
56
57 m_scenes.Add(scene);
58 scene.EventManager.OnNewClient += OnNewClient;
59 }
60
61 public void PostInitialise()
62 {
63 }
64
65 public void Close()
66 {
67 m_scene = null;
68 m_scenes.Clear();
69 }
70
71 public string Name
72 {
73 get { return "MapSearchModule"; }
74 }
75
76 public bool IsSharedModule
77 {
78 get { return true; }
79 }
80
81 #endregion
82
83 private void OnNewClient(IClientAPI client)
84 {
85 client.OnMapNameRequest += OnMapNameRequest;
86 }
87
88 private void OnMapNameRequest(IClientAPI remoteClient, string mapName)
89 {
90 if (mapName.Length < 3)
91 {
92 remoteClient.SendAlertMessage("Use a search string with at least 3 characters");
93 return;
94 }
95
96 // try to fetch from GridServer
97 List<RegionInfo> regionInfos = m_scene.SceneGridService.RequestNamedRegions(mapName, 20);
98 if (regionInfos == null)
99 {
100 m_log.Warn("[MAPSEARCHMODULE]: RequestNamedRegions returned null. Old gridserver?");
101 // service wasn't available; maybe still an old GridServer. Try the old API, though it will return only one region
102 regionInfos = new List<RegionInfo>();
103 RegionInfo info = m_scene.SceneGridService.RequestClosestRegion(mapName);
104 if (info != null) regionInfos.Add(info);
105 }
106
107 if ((regionInfos.Count == 0) && IsHypergridOn())
108 {
109 // OK, we tried but there are no regions matching that name.
110 // Let's check quickly if this is a domain name, and if so link to it
111 if (mapName.Contains(".") && mapName.Contains(":"))
112 {
113 // It probably is a domain name. Try to link to it.
114 RegionInfo regInfo;
115 Scene cScene = GetClientScene(remoteClient);
116 regInfo = HGHyperlink.TryLinkRegion(cScene, remoteClient, mapName);
117 if (regInfo != null)
118 regionInfos.Add(regInfo);
119 }
120 }
121
122 List<MapBlockData> blocks = new List<MapBlockData>();
123
124 MapBlockData data;
125 if (regionInfos.Count > 0)
126 {
127 foreach (RegionInfo info in regionInfos)
128 {
129 data = new MapBlockData();
130 data.Agents = 0;
131 data.Access = 21; // TODO what's this?
132 data.MapImageId = info.RegionSettings.TerrainImageID;
133 data.Name = info.RegionName;
134 data.RegionFlags = 0; // TODO not used?
135 data.WaterHeight = 0; // not used
136 data.X = (ushort)info.RegionLocX;
137 data.Y = (ushort)info.RegionLocY;
138 blocks.Add(data);
139 }
140 }
141
142 // final block, closing the search result
143 data = new MapBlockData();
144 data.Agents = 0;
145 data.Access = 255;
146 data.MapImageId = UUID.Zero;
147 data.Name = mapName;
148 data.RegionFlags = 0;
149 data.WaterHeight = 0; // not used
150 data.X = 0;
151 data.Y = 0;
152 blocks.Add(data);
153
154 remoteClient.SendMapBlock(blocks, 0);
155 }
156
157 private bool IsHypergridOn()
158 {
159 return (m_scene.SceneGridService is HGSceneCommunicationService);
160 }
161
162 private Scene GetClientScene(IClientAPI client)
163 {
164 foreach (Scene s in m_scenes)
165 {
166 if (client.Scene.RegionInfo.RegionHandle == s.RegionInfo.RegionHandle)
167 return s;
168 }
169 return m_scene;
170 }
171 }
172}
diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/ShadedMapTileRenderer.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/ShadedMapTileRenderer.cs
deleted file mode 100644
index 7fe538e..0000000
--- a/OpenSim/Region/Environment/Modules/World/WorldMap/ShadedMapTileRenderer.cs
+++ /dev/null
@@ -1,249 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Drawing;
32using System.Drawing.Drawing2D;
33using System.Drawing.Imaging;
34using System.Reflection;
35using OpenMetaverse;
36using OpenMetaverse.Imaging;
37using Nini.Config;
38using log4net;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.Environment.Modules.World.WorldMap
43{
44 public class ShadedMapTileRenderer : IMapTileTerrainRenderer
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private Scene m_scene;
50 //private IConfigSource m_config; // not used currently
51
52 public void Initialise(Scene scene, IConfigSource config)
53 {
54 m_scene = scene;
55 // m_config = config; // not used currently
56 }
57
58 public void TerrainToBitmap(Bitmap mapbmp)
59 {
60 int tc = System.Environment.TickCount;
61 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain");
62
63 double[,] hm = m_scene.Heightmap.GetDoubles();
64 bool ShadowDebugContinue = true;
65
66 bool terraincorruptedwarningsaid = false;
67
68 float low = 255;
69 float high = 0;
70 for (int x = 0; x < 256; x++)
71 {
72 for (int y = 0; y < 256; y++)
73 {
74 float hmval = (float)hm[x, y];
75 if (hmval < low)
76 low = hmval;
77 if (hmval > high)
78 high = hmval;
79 }
80 }
81
82 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
83
84 for (int x = 0; x < 256; x++)
85 {
86 for (int y = 0; y < 256; y++)
87 {
88 // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left
89 int yr = 255 - y;
90
91 float heightvalue = (float)hm[x, y];
92
93 if (heightvalue > waterHeight)
94 {
95 // scale height value
96 // No, that doesn't scale it:
97 // heightvalue = low + mid * (heightvalue - low) / mid; => low + (heightvalue - low) * mid / mid = low + (heightvalue - low) * 1 = low + heightvalue - low = heightvalue
98
99 if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue))
100 heightvalue = 0;
101 else if (heightvalue > 255f)
102 heightvalue = 255f;
103 else if (heightvalue < 0f)
104 heightvalue = 0f;
105
106 Color color = Color.FromArgb((int)heightvalue, 100, (int)heightvalue);
107
108 mapbmp.SetPixel(x, yr, color);
109
110 try
111 {
112 //X
113 // .
114 //
115 // Shade the terrain for shadows
116 if (x < 255 && yr < 255)
117 {
118 float hfvalue = (float)hm[x, y];
119 float hfvaluecompare = 0f;
120
121 if ((x + 1 < 256) && (y + 1 < 256))
122 {
123 hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there
124 }
125 if (Single.IsInfinity(hfvalue) || Single.IsNaN(hfvalue))
126 hfvalue = 0f;
127
128 if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare))
129 hfvaluecompare = 0f;
130
131 float hfdiff = hfvalue - hfvaluecompare; // => positive if NE is lower, negative if here is lower
132
133 int hfdiffi = 0;
134 int hfdiffihighlight = 0;
135 float highlightfactor = 0.18f;
136
137 try
138 {
139 // hfdiffi = Math.Abs((int)((hfdiff * 4) + (hfdiff * 0.5))) + 1;
140 hfdiffi = Math.Abs((int)(hfdiff * 4.5f)) + 1;
141 if (hfdiff % 1f != 0)
142 {
143 // hfdiffi = hfdiffi + Math.Abs((int)(((hfdiff % 1) * 0.5f) * 10f) - 1);
144 hfdiffi = hfdiffi + Math.Abs((int)((hfdiff % 1f) * 5f) - 1);
145 }
146
147 hfdiffihighlight = Math.Abs((int)((hfdiff * highlightfactor) * 4.5f)) + 1;
148 if (hfdiff % 1f != 0)
149 {
150 // hfdiffi = hfdiffi + Math.Abs((int)(((hfdiff % 1) * 0.5f) * 10f) - 1);
151 hfdiffihighlight = hfdiffihighlight + Math.Abs((int)(((hfdiff * highlightfactor) % 1f) * 5f) - 1);
152 }
153 }
154 catch (System.OverflowException)
155 {
156 m_log.Debug("[MAPTILE]: Shadow failed at value: " + hfdiff.ToString());
157 ShadowDebugContinue = false;
158 }
159
160 if (hfdiff > 0.3f)
161 {
162 // NE is lower than here
163 // We have to desaturate and lighten the land at the same time
164 // we use floats, colors use bytes, so shrink are space down to
165 // 0-255
166
167 if (ShadowDebugContinue)
168 {
169 int r = color.R;
170 int g = color.G;
171 int b = color.B;
172 color = Color.FromArgb((r + hfdiffihighlight < 255) ? r + hfdiffihighlight : 255,
173 (g + hfdiffihighlight < 255) ? g + hfdiffihighlight : 255,
174 (b + hfdiffihighlight < 255) ? b + hfdiffihighlight : 255);
175 }
176 }
177 else if (hfdiff < -0.3f)
178 {
179 // here is lower than NE:
180 // We have to desaturate and blacken the land at the same time
181 // we use floats, colors use bytes, so shrink are space down to
182 // 0-255
183
184 if (ShadowDebugContinue)
185 {
186 if ((x - 1 > 0) && (yr + 1 < 256))
187 {
188 color = mapbmp.GetPixel(x - 1, yr + 1);
189 int r = color.R;
190 int g = color.G;
191 int b = color.B;
192 color = Color.FromArgb((r - hfdiffi > 0) ? r - hfdiffi : 0,
193 (g - hfdiffi > 0) ? g - hfdiffi : 0,
194 (b - hfdiffi > 0) ? b - hfdiffi : 0);
195
196 mapbmp.SetPixel(x-1, yr+1, color);
197 }
198 }
199 }
200 }
201 }
202 catch (System.ArgumentException)
203 {
204 if (!terraincorruptedwarningsaid)
205 {
206 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
207 terraincorruptedwarningsaid = true;
208 }
209 color = Color.Black;
210 mapbmp.SetPixel(x, yr, color);
211 }
212 }
213 else
214 {
215 // We're under the water level with the terrain, so paint water instead of land
216
217 // Y flip the cordinates
218 heightvalue = waterHeight - heightvalue;
219 if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue))
220 heightvalue = 0f;
221 else if (heightvalue > 19f)
222 heightvalue = 19f;
223 else if (heightvalue < 0f)
224 heightvalue = 0f;
225
226 heightvalue = 100f - (heightvalue * 100f) / 19f;
227
228 try
229 {
230 Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255);
231 mapbmp.SetPixel(x, yr, water);
232 }
233 catch (System.ArgumentException)
234 {
235 if (!terraincorruptedwarningsaid)
236 {
237 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
238 terraincorruptedwarningsaid = true;
239 }
240 Color black = Color.Black;
241 mapbmp.SetPixel(x, (256 - y) - 1, black);
242 }
243 }
244 }
245 }
246 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (System.Environment.TickCount - tc) + " ms");
247 }
248 }
249}
diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/TexturedMapTileRenderer.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/TexturedMapTileRenderer.cs
deleted file mode 100644
index d23c352..0000000
--- a/OpenSim/Region/Environment/Modules/World/WorldMap/TexturedMapTileRenderer.cs
+++ /dev/null
@@ -1,411 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Drawing;
32using System.Drawing.Drawing2D;
33using System.Drawing.Imaging;
34using System.Reflection;
35using OpenMetaverse;
36using Nini.Config;
37using log4net;
38using OpenMetaverse.Imaging;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.Environment.Modules.World.Terrain;
43
44namespace OpenSim.Region.Environment.Modules.World.WorldMap
45{
46 // Hue, Saturation, Value; used for color-interpolation
47 struct HSV {
48 public float h;
49 public float s;
50 public float v;
51
52 public HSV(float h, float s, float v)
53 {
54 this.h = h;
55 this.s = s;
56 this.v = v;
57 }
58
59 // (for info about algorithm, see http://en.wikipedia.org/wiki/HSL_and_HSV)
60 public HSV(Color c)
61 {
62 float r = c.R / 255f;
63 float g = c.G / 255f;
64 float b = c.B / 255f;
65 float max = Math.Max(Math.Max(r, g), b);
66 float min = Math.Min(Math.Min(r, g), b);
67 float diff = max - min;
68
69 if (max == min) h = 0f;
70 else if (max == r) h = (g - b) / diff * 60f;
71 else if (max == g) h = (b - r) / diff * 60f + 120f;
72 else h = (r - g) / diff * 60f + 240f;
73 if (h < 0f) h += 360f;
74
75 if (max == 0f) s = 0f;
76 else s = diff / max;
77
78 v = max;
79 }
80
81 // (for info about algorithm, see http://en.wikipedia.org/wiki/HSL_and_HSV)
82 public Color toColor()
83 {
84 if (s < 0f) Console.WriteLine("S < 0: " + s);
85 else if (s > 1f) Console.WriteLine("S > 1: " + s);
86 if (v < 0f) Console.WriteLine("V < 0: " + v);
87 else if (v > 1f) Console.WriteLine("V > 1: " + v);
88
89 float f = h / 60f;
90 int sector = (int)f % 6;
91 f = f - (int)f;
92 int pi = (int)(v * (1f - s) * 255f);
93 int qi = (int)(v * (1f - s * f) * 255f);
94 int ti = (int)(v * (1f - (1f - f) * s) * 255f);
95 int vi = (int)(v * 255f);
96
97 switch (sector)
98 {
99 case 0:
100 return Color.FromArgb(vi, ti, pi);
101 case 1:
102 return Color.FromArgb(qi, vi, pi);
103 case 2:
104 return Color.FromArgb(pi, vi, ti);
105 case 3:
106 return Color.FromArgb(pi, qi, vi);
107 case 4:
108 return Color.FromArgb(ti, pi, vi);
109 default:
110 return Color.FromArgb(vi, pi, qi);
111 }
112 }
113 }
114
115 public class TexturedMapTileRenderer : IMapTileTerrainRenderer
116 {
117 #region Constants
118
119 private static readonly ILog m_log =
120 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
121
122 // some hardcoded terrain UUIDs that work with SL 1.20 (the four default textures and "Blank").
123 // The color-values were choosen because they "look right" (at least to me) ;-)
124 private static readonly UUID defaultTerrainTexture1 = new UUID("0bc58228-74a0-7e83-89bc-5c23464bcec5");
125 private static readonly Color defaultColor1 = Color.FromArgb(165, 137, 118);
126 private static readonly UUID defaultTerrainTexture2 = new UUID("63338ede-0037-c4fd-855b-015d77112fc8");
127 private static readonly Color defaultColor2 = Color.FromArgb(69, 89, 49);
128 private static readonly UUID defaultTerrainTexture3 = new UUID("303cd381-8560-7579-23f1-f0a880799740");
129 private static readonly Color defaultColor3 = Color.FromArgb(162, 154, 141);
130 private static readonly UUID defaultTerrainTexture4 = new UUID("53a2f406-4895-1d13-d541-d2e3b86bc19c");
131 private static readonly Color defaultColor4 = Color.FromArgb(200, 200, 200);
132
133 #endregion
134
135
136 private Scene m_scene;
137 // private IConfigSource m_config; // not used currently
138
139 // mapping from texture UUIDs to averaged color. This will contain 5-9 values, in general; new values are only
140 // added when the terrain textures are changed in the estate dialog and a new map is generated (and will stay in
141 // that map until the region-server restarts. This could be considered a memory-leak, but it's a *very* small one.
142 // TODO does it make sense to use a "real" cache and regenerate missing entries on fetch?
143 private Dictionary<UUID, Color> m_mapping;
144
145
146 public void Initialise(Scene scene, IConfigSource source)
147 {
148 m_scene = scene;
149 // m_config = source; // not used currently
150 m_mapping = new Dictionary<UUID,Color>();
151 m_mapping.Add(defaultTerrainTexture1, defaultColor1);
152 m_mapping.Add(defaultTerrainTexture2, defaultColor2);
153 m_mapping.Add(defaultTerrainTexture3, defaultColor3);
154 m_mapping.Add(defaultTerrainTexture4, defaultColor4);
155 m_mapping.Add(Util.BLANK_TEXTURE_UUID, Color.White);
156 }
157
158 #region Helpers
159 // This fetches the texture from the asset server synchroneously. That should be ok, as we
160 // call map-creation only in those places:
161 // - on start: We can wait here until the asset server returns the texture
162 // TODO (- on "map" command: We are in the command-line thread, we will wait for completion anyway)
163 // TODO (- on "automatic" update after some change: We are called from the mapUpdateTimer here and
164 // will wait anyway)
165 private Bitmap fetchTexture(UUID id)
166 {
167 AssetBase asset = m_scene.AssetCache.GetAsset(id, true);
168 m_log.DebugFormat("Fetched texture {0}, found: {1}", id, asset != null);
169 if (asset == null) return null;
170
171 ManagedImage managedImage;
172 Image image;
173
174 try
175 {
176 if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image))
177 return new Bitmap(image);
178 else
179 return null;
180 }
181 catch (DllNotFoundException)
182 {
183 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system. Asset Data is emtpy for {0}", id);
184
185 }
186 catch (IndexOutOfRangeException)
187 {
188 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", id);
189
190 }
191 catch (Exception)
192 {
193 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", id);
194
195 }
196 return null;
197
198 }
199
200 // Compute the average color of a texture.
201 private Color computeAverageColor(Bitmap bmp)
202 {
203 // we have 256 x 256 pixel, each with 256 possible color-values per
204 // color-channel, so 2^24 is the maximum value we can get, adding everything.
205 // int is be big enough for that.
206 int r = 0, g = 0, b = 0;
207 for (int y = 0; y < bmp.Height; ++y)
208 {
209 for (int x = 0; x < bmp.Width; ++x)
210 {
211 Color c = bmp.GetPixel(x, y);
212 r += (int)c.R & 0xff;
213 g += (int)c.G & 0xff;
214 b += (int)c.B & 0xff;
215 }
216 }
217
218 int pixels = bmp.Width * bmp.Height;
219 return Color.FromArgb(r / pixels, g / pixels, b / pixels);
220 }
221
222 // return either the average color of the texture, or the defaultColor if the texturID is invalid
223 // or the texture couldn't be found
224 private Color computeAverageColor(UUID textureID, Color defaultColor) {
225 if (textureID == UUID.Zero) return defaultColor; // not set
226 if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures
227
228 Bitmap bmp = fetchTexture(textureID);
229 Color color = bmp == null ? defaultColor : computeAverageColor(bmp);
230 // store it for future reference
231 m_mapping[textureID] = color;
232
233 return color;
234 }
235
236 // S-curve: f(x) = 3x² - 2x³:
237 // f(0) = 0, f(0.5) = 0.5, f(1) = 1,
238 // f'(x) = 0 at x = 0 and x = 1; f'(0.5) = 1.5,
239 // f''(0.5) = 0, f''(x) != 0 for x != 0.5
240 private float S(float v) {
241 return (v * v * (3f - 2f * v));
242 }
243
244 // interpolate two colors in HSV space and return the resulting color
245 private HSV interpolateHSV(ref HSV c1, ref HSV c2, float ratio) {
246 if (ratio <= 0f) return c1;
247 if (ratio >= 1f) return c2;
248
249 // make sure we are on the same side on the hue-circle for interpolation
250 // We change the hue of the parameters here, but we don't change the color
251 // represented by that value
252 if (c1.h - c2.h > 180f) c1.h -= 360f;
253 else if (c2.h - c1.h > 180f) c1.h += 360f;
254
255 return new HSV(c1.h * (1f - ratio) + c2.h * ratio,
256 c1.s * (1f - ratio) + c2.s * ratio,
257 c1.v * (1f - ratio) + c2.v * ratio);
258 }
259
260 // the heigthfield might have some jumps in values. Rendered land is smooth, though,
261 // as a slope is rendered at that place. So average 4 neighbour values to emulate that.
262 private float getHeight(double[,] hm, int x, int y) {
263 if (x < 255 && y < 255)
264 return (float)(hm[x, y] * .444 + (hm[x + 1, y] + hm[x, y + 1]) * .222 + hm[x + 1, y +1] * .112);
265 else
266 return (float)hm[x, y];
267 }
268 #endregion
269
270 public void TerrainToBitmap(Bitmap mapbmp)
271 {
272 int tc = System.Environment.TickCount;
273 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain");
274
275 // These textures should be in the AssetCache anyway, as every client conneting to this
276 // region needs them. Except on start, when the map is recreated (before anyone connected),
277 // and on change of the estate settings (textures and terrain values), when the map should
278 // be recreated.
279 RegionSettings settings = m_scene.RegionInfo.RegionSettings;
280
281 // the four terrain colors as HSVs for interpolation
282 HSV hsv1 = new HSV(computeAverageColor(settings.TerrainTexture1, defaultColor1));
283 HSV hsv2 = new HSV(computeAverageColor(settings.TerrainTexture2, defaultColor2));
284 HSV hsv3 = new HSV(computeAverageColor(settings.TerrainTexture3, defaultColor3));
285 HSV hsv4 = new HSV(computeAverageColor(settings.TerrainTexture4, defaultColor4));
286
287 float levelNElow = (float)settings.Elevation1NE;
288 float levelNEhigh = (float)settings.Elevation2NE;
289
290 float levelNWlow = (float)settings.Elevation1NW;
291 float levelNWhigh = (float)settings.Elevation2NW;
292
293 float levelSElow = (float)settings.Elevation1SE;
294 float levelSEhigh = (float)settings.Elevation2SE;
295
296 float levelSWlow = (float)settings.Elevation1SW;
297 float levelSWhigh = (float)settings.Elevation2SW;
298
299 float waterHeight = (float)settings.WaterHeight;
300
301 double[,] hm = m_scene.Heightmap.GetDoubles();
302
303 for (int x = 0; x < 256; x++)
304 {
305 float columnRatio = x / 255f; // 0 - 1, for interpolation
306 for (int y = 0; y < 256; y++)
307 {
308 float rowRatio = y / 255f; // 0 - 1, for interpolation
309
310 // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left
311 int yr = 255 - y;
312
313 float heightvalue = getHeight(hm, x, y);
314 if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue))
315 heightvalue = 0;
316
317 if (heightvalue > waterHeight)
318 {
319 // add a bit noise for breaking up those flat colors:
320 // - a large-scale noise, for the "patches" (using an doubled s-curve for sharper contrast)
321 // - a small-scale noise, for bringing in some small scale variation
322 //float bigNoise = (float)TerrainUtil.InterpolatedNoise(x / 8.0, y / 8.0) * .5f + .5f; // map to 0.0 - 1.0
323 //float smallNoise = (float)TerrainUtil.InterpolatedNoise(x + 33, y + 43) * .5f + .5f;
324 //float hmod = heightvalue + smallNoise * 3f + S(S(bigNoise)) * 10f;
325 float hmod =
326 heightvalue +
327 (float)TerrainUtil.InterpolatedNoise(x + 33, y + 43) * 1.5f + 1.5f + // 0 - 3
328 S(S((float)TerrainUtil.InterpolatedNoise(x / 8.0, y / 8.0) * .5f + .5f)) * 10f; // 0 - 10
329
330 // find the low/high values for this point (interpolated bilinearily)
331 // (and remember, x=0,y=0 is SW)
332 float low = levelSWlow * (1f - rowRatio) * (1f - columnRatio) +
333 levelSElow * (1f - rowRatio) * columnRatio +
334 levelNWlow * rowRatio * (1f - columnRatio) +
335 levelNElow * rowRatio * columnRatio;
336 float high = levelSWhigh * (1f - rowRatio) * (1f - columnRatio) +
337 levelSEhigh * (1f - rowRatio) * columnRatio +
338 levelNWhigh * rowRatio * (1f - columnRatio) +
339 levelNEhigh * rowRatio * columnRatio;
340 if (high < low)
341 {
342 // someone tried to fool us. High value should be higher than low every time
343 float tmp = high;
344 high = low;
345 low = tmp;
346 }
347
348 HSV hsv;
349 if (hmod <= low) hsv = hsv1; // too low
350 else if (hmod >= high) hsv = hsv4; // too high
351 else
352 {
353 // HSV-interpolate along the colors
354 // first, rescale h to 0.0 - 1.0
355 hmod = (hmod - low) / (high - low);
356 // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4
357 if (hmod < 1f/3f) hsv = interpolateHSV(ref hsv1, ref hsv2, hmod * 3f);
358 else if (hmod < 2f/3f) hsv = interpolateHSV(ref hsv2, ref hsv3, (hmod * 3f) - 1f);
359 else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f);
360 }
361
362 // Shade the terrain for shadows
363 if (x < 255 && y < 255)
364 {
365 float hfvaluecompare = getHeight(hm, x + 1, y + 1); // light from north-east => look at land height there
366 if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare))
367 hfvaluecompare = 0f;
368
369 float hfdiff = heightvalue - hfvaluecompare; // => positive if NE is lower, negative if here is lower
370 hfdiff *= 0.06f; // some random factor so "it looks good"
371 if (hfdiff > 0.02f)
372 {
373 float highlightfactor = 0.18f;
374 // NE is lower than here
375 // We have to desaturate and lighten the land at the same time
376 hsv.s = (hsv.s - (hfdiff * highlightfactor) > 0f) ? hsv.s - (hfdiff * highlightfactor) : 0f;
377 hsv.v = (hsv.v + (hfdiff * highlightfactor) < 1f) ? hsv.v + (hfdiff * highlightfactor) : 1f;
378 }
379 else if (hfdiff < -0.02f)
380 {
381 // here is lower than NE:
382 // We have to desaturate and blacken the land at the same time
383 hsv.s = (hsv.s + hfdiff > 0f) ? hsv.s + hfdiff : 0f;
384 hsv.v = (hsv.v + hfdiff > 0f) ? hsv.v + hfdiff : 0f;
385 }
386 }
387 mapbmp.SetPixel(x, yr, hsv.toColor());
388 }
389 else
390 {
391 // We're under the water level with the terrain, so paint water instead of land
392
393 heightvalue = waterHeight - heightvalue;
394 if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue))
395 heightvalue = 0f;
396 else if (heightvalue > 19f)
397 heightvalue = 19f;
398 else if (heightvalue < 0f)
399 heightvalue = 0f;
400
401 heightvalue = 100f - (heightvalue * 100f) / 19f; // 0 - 19 => 100 - 0
402
403 Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255);
404 mapbmp.SetPixel(x, yr, water);
405 }
406 }
407 }
408 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (System.Environment.TickCount - tc) + " ms");
409 }
410 }
411}
diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/WorldMapModule.cs
deleted file mode 100644
index 37b4547..0000000
--- a/OpenSim/Region/Environment/Modules/World/WorldMap/WorldMapModule.cs
+++ /dev/null
@@ -1,905 +0,0 @@
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 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 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Drawing;
32using System.Drawing.Imaging;
33using System.IO;
34using System.Net;
35using System.Reflection;
36using System.Threading;
37using OpenMetaverse;
38using OpenMetaverse.Imaging;
39using OpenMetaverse.StructuredData;
40using log4net;
41using Nini.Config;
42using OpenSim.Framework;
43using OpenSim.Framework.Communications.Cache;
44using OpenSim.Framework.Communications.Capabilities;
45using OpenSim.Framework.Servers;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Framework.Scenes.Types;
49using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
50
51using OSD = OpenMetaverse.StructuredData.OSD;
52using OSDMap = OpenMetaverse.StructuredData.OSDMap;
53using OSDArray = OpenMetaverse.StructuredData.OSDArray;
54
55namespace OpenSim.Region.Environment.Modules.World.WorldMap
56{
57 public class WorldMapModule : IRegionModule
58 {
59 private static readonly ILog m_log =
60 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61
62 private static readonly string m_mapLayerPath = "0001/";
63
64 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
65
66 //private IConfig m_config;
67 protected Scene m_scene;
68 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
69 private int cachedTime = 0;
70 private byte[] myMapImageJPEG;
71 protected bool m_Enabled = false;
72 private Dictionary<UUID, MapRequestState> m_openRequests = new Dictionary<UUID, MapRequestState>();
73 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>();
74 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>();
75 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>();
76 private List<UUID> m_rootAgents = new List<UUID>();
77 private Thread mapItemReqThread;
78 private volatile bool threadrunning = false;
79
80 //private int CacheRegionsDistance = 256;
81
82 #region IRegionModule Members
83
84 public virtual void Initialise(Scene scene, IConfigSource config)
85 {
86 IConfig startupConfig = config.Configs["Startup"];
87 if (startupConfig.GetString("WorldMapModule", "WorldMap") ==
88 "WorldMap")
89 m_Enabled = true;
90
91 if (!m_Enabled)
92 return;
93
94 m_scene = scene;
95 }
96
97 public virtual void PostInitialise()
98 {
99 if (m_Enabled)
100 AddHandlers();
101 }
102
103 public virtual void Close()
104 {
105 }
106
107 public virtual string Name
108 {
109 get { return "WorldMapModule"; }
110 }
111
112 public bool IsSharedModule
113 {
114 get { return false; }
115 }
116
117 #endregion
118
119 protected virtual void AddHandlers()
120 {
121 myMapImageJPEG = new byte[0];
122
123 string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString();
124 regionimage = regionimage.Replace("-", "");
125 m_log.Info("[WORLD MAP]: JPEG Map location: http://" + m_scene.RegionInfo.ExternalEndPoint.Address.ToString() + ":" + m_scene.RegionInfo.HttpPort.ToString() + "/index.php?method=" + regionimage);
126
127 m_scene.CommsManager.HttpServer.AddHTTPHandler(regionimage, OnHTTPGetMapImage);
128 m_scene.CommsManager.HttpServer.AddLLSDHandler(
129 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest);
130
131 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
132 m_scene.EventManager.OnNewClient += OnNewClient;
133 m_scene.EventManager.OnClientClosed += ClientLoggedOut;
134 m_scene.EventManager.OnMakeChildAgent += MakeChildAgent;
135 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent;
136 }
137
138 public void OnRegisterCaps(UUID agentID, Caps caps)
139 {
140 //m_log.DebugFormat("[WORLD MAP]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
141 string capsBase = "/CAPS/" + caps.CapsObjectPath;
142 caps.RegisterHandler("MapLayer",
143 new RestStreamHandler("POST", capsBase + m_mapLayerPath,
144 delegate(string request, string path, string param,
145 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
146 {
147 return MapLayerRequest(request, path, param,
148 agentID, caps);
149 }));
150 }
151
152 /// <summary>
153 /// Callback for a map layer request
154 /// </summary>
155 /// <param name="request"></param>
156 /// <param name="path"></param>
157 /// <param name="param"></param>
158 /// <param name="agentID"></param>
159 /// <param name="caps"></param>
160 /// <returns></returns>
161 public string MapLayerRequest(string request, string path, string param,
162 UUID agentID, Caps caps)
163 {
164 //try
165 //{
166 //m_log.DebugFormat("[MAPLAYER]: request: {0}, path: {1}, param: {2}, agent:{3}",
167 //request, path, param,agentID.ToString());
168
169 // this is here because CAPS map requests work even beyond the 10,000 limit.
170 ScenePresence avatarPresence = null;
171
172 m_scene.TryGetAvatar(agentID, out avatarPresence);
173
174 if (avatarPresence != null)
175 {
176 bool lookup = false;
177
178 lock (cachedMapBlocks)
179 {
180 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
181 {
182 List<MapBlockData> mapBlocks;
183
184 mapBlocks = cachedMapBlocks;
185 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
186 }
187 else
188 {
189 lookup = true;
190 }
191 }
192 if (lookup)
193 {
194 List<MapBlockData> mapBlocks;
195
196 mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks((int)m_scene.RegionInfo.RegionLocX - 8, (int)m_scene.RegionInfo.RegionLocY - 8, (int)m_scene.RegionInfo.RegionLocX + 8, (int)m_scene.RegionInfo.RegionLocY + 8);
197 avatarPresence.ControllingClient.SendMapBlock(mapBlocks,0);
198
199 lock (cachedMapBlocks)
200 cachedMapBlocks = mapBlocks;
201
202 cachedTime = Util.UnixTimeSinceEpoch();
203 }
204 }
205 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
206 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
207 return mapResponse.ToString();
208 }
209
210 /// <summary>
211 ///
212 /// </summary>
213 /// <param name="mapReq"></param>
214 /// <returns></returns>
215 public LLSDMapLayerResponse GetMapLayer(LLSDMapRequest mapReq)
216 {
217 m_log.Debug("[WORLD MAP]: MapLayer Request in region: " + m_scene.RegionInfo.RegionName);
218 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
219 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
220 return mapResponse;
221 }
222
223 /// <summary>
224 ///
225 /// </summary>
226 /// <returns></returns>
227 protected static OSDMapLayer GetOSDMapLayerResponse()
228 {
229 OSDMapLayer mapLayer = new OSDMapLayer();
230 mapLayer.Right = 5000;
231 mapLayer.Top = 5000;
232 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
233
234 return mapLayer;
235 }
236 #region EventHandlers
237
238 /// <summary>
239 /// Registered for event
240 /// </summary>
241 /// <param name="client"></param>
242 private void OnNewClient(IClientAPI client)
243 {
244 client.OnRequestMapBlocks += RequestMapBlocks;
245 client.OnMapItemRequest += HandleMapItemRequest;
246 }
247
248 /// <summary>
249 /// Client logged out, check to see if there are any more root agents in the simulator
250 /// If not, stop the mapItemRequest Thread
251 /// Event handler
252 /// </summary>
253 /// <param name="AgentId">AgentID that logged out</param>
254 private void ClientLoggedOut(UUID AgentId)
255 {
256 List<ScenePresence> presences = m_scene.GetAvatars();
257 int rootcount = 0;
258 for (int i=0;i<presences.Count;i++)
259 {
260 if (presences[i] != null)
261 {
262 if (!presences[i].IsChildAgent)
263 rootcount++;
264 }
265 }
266 if (rootcount <= 1)
267 StopThread();
268
269 lock (m_rootAgents)
270 {
271 if (m_rootAgents.Contains(AgentId))
272 {
273 m_rootAgents.Remove(AgentId);
274 }
275 }
276 }
277 #endregion
278
279 /// <summary>
280 /// Starts the MapItemRequest Thread
281 /// Note that this only gets started when there are actually agents in the region
282 /// Additionally, it gets stopped when there are none.
283 /// </summary>
284 /// <param name="o"></param>
285 private void StartThread(object o)
286 {
287 if (threadrunning) return;
288 threadrunning = true;
289 m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread");
290 mapItemReqThread = new Thread(new ThreadStart(process));
291 mapItemReqThread.IsBackground = true;
292 mapItemReqThread.Name = "MapItemRequestThread";
293 mapItemReqThread.Priority = ThreadPriority.BelowNormal;
294 mapItemReqThread.SetApartmentState(ApartmentState.MTA);
295 mapItemReqThread.Start();
296 ThreadTracker.Add(mapItemReqThread);
297 }
298
299 /// <summary>
300 /// Enqueues a 'stop thread' MapRequestState. Causes the MapItemRequest thread to end
301 /// </summary>
302 private void StopThread()
303 {
304 MapRequestState st = new MapRequestState();
305 st.agentID=UUID.Zero;
306 st.EstateID=0;
307 st.flags=0;
308 st.godlike=false;
309 st.itemtype=0;
310 st.regionhandle=0;
311
312 requests.Enqueue(st);
313 }
314
315 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
316 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
317 {
318 lock (m_rootAgents)
319 {
320 if (!m_rootAgents.Contains(remoteClient.AgentId))
321 return;
322 }
323 uint xstart = 0;
324 uint ystart = 0;
325 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
326 if (itemtype == 6) // we only sevice 6 right now (avatar green dots)
327 {
328 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle)
329 {
330 // Local Map Item Request
331 List<ScenePresence> avatars = m_scene.GetAvatars();
332 int tc = System.Environment.TickCount;
333 List<mapItemReply> mapitems = new List<mapItemReply>();
334 mapItemReply mapitem = new mapItemReply();
335 if (avatars.Count == 0 || avatars.Count == 1)
336 {
337 mapitem = new mapItemReply();
338 mapitem.x = (uint)(xstart + 1);
339 mapitem.y = (uint)(ystart + 1);
340 mapitem.id = UUID.Zero;
341 mapitem.name = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString());
342 mapitem.Extra = 0;
343 mapitem.Extra2 = 0;
344 mapitems.Add(mapitem);
345 }
346 else
347 {
348 foreach (ScenePresence av in avatars)
349 {
350 // Don't send a green dot for yourself
351 if (av.UUID != remoteClient.AgentId)
352 {
353 mapitem = new mapItemReply();
354 mapitem.x = (uint)(xstart + av.AbsolutePosition.X);
355 mapitem.y = (uint)(ystart + av.AbsolutePosition.Y);
356 mapitem.id = UUID.Zero;
357 mapitem.name = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString());
358 mapitem.Extra = 1;
359 mapitem.Extra2 = 0;
360 mapitems.Add(mapitem);
361 }
362 }
363 }
364 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
365 }
366 else
367 {
368 // Remote Map Item Request
369
370 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes.
371 // Note that we only start up a remote mapItem Request thread if there's users who could
372 // be making requests
373 if (!threadrunning)
374 {
375 m_log.Warn("[WORLD MAP]: Starting new remote request thread manually. This means that AvatarEnteringParcel never fired! This needs to be fixed! Don't Mantis this, as the developers can see it in this message");
376 StartThread(new object());
377 }
378
379 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle);
380 }
381 }
382 }
383
384 /// <summary>
385 /// Processing thread main() loop for doing remote mapitem requests
386 /// </summary>
387 public void process()
388 {
389 try
390 {
391 while (true)
392 {
393 MapRequestState st = requests.Dequeue();
394
395 // end gracefully
396 if (st.agentID == UUID.Zero)
397 {
398 ThreadTracker.Remove(mapItemReqThread);
399 break;
400 }
401
402 bool dorequest = true;
403 lock (m_rootAgents)
404 {
405 if (!m_rootAgents.Contains(st.agentID))
406 dorequest = false;
407 }
408
409 if (dorequest)
410 {
411 OSDMap response = RequestMapItemsAsync("", st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
412 RequestMapItemsCompleted(response);
413 }
414 }
415 }
416 catch (Exception e)
417 {
418 m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
419 }
420
421 threadrunning = false;
422 }
423
424 /// <summary>
425 /// Enqueues the map item request into the processing thread
426 /// </summary>
427 /// <param name="state"></param>
428 public void EnqueueMapItemRequest(MapRequestState state)
429 {
430 requests.Enqueue(state);
431 }
432
433 /// <summary>
434 /// Sends the mapitem response to the IClientAPI
435 /// </summary>
436 /// <param name="response">The OSDMap Response for the mapitem</param>
437 private void RequestMapItemsCompleted(OSDMap response)
438 {
439 UUID requestID = response["requestID"].AsUUID();
440
441 if (requestID != UUID.Zero)
442 {
443 MapRequestState mrs = new MapRequestState();
444 mrs.agentID = UUID.Zero;
445 lock (m_openRequests)
446 {
447 if (m_openRequests.ContainsKey(requestID))
448 {
449 mrs = m_openRequests[requestID];
450 m_openRequests.Remove(requestID);
451 }
452 }
453
454 if (mrs.agentID != UUID.Zero)
455 {
456 ScenePresence av = null;
457 m_scene.TryGetAvatar(mrs.agentID, out av);
458 if (av != null)
459 {
460 if (response.ContainsKey(mrs.itemtype.ToString()))
461 {
462 List<mapItemReply> returnitems = new List<mapItemReply>();
463 OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()];
464 for (int i = 0; i < itemarray.Count; i++)
465 {
466 OSDMap mapitem = (OSDMap)itemarray[i];
467 mapItemReply mi = new mapItemReply();
468 mi.x = (uint)mapitem["X"].AsInteger();
469 mi.y = (uint)mapitem["Y"].AsInteger();
470 mi.id = mapitem["ID"].AsUUID();
471 mi.Extra = mapitem["Extra"].AsInteger();
472 mi.Extra2 = mapitem["Extra2"].AsInteger();
473 mi.name = mapitem["Name"].AsString();
474 returnitems.Add(mi);
475 }
476 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags);
477 }
478 }
479 }
480 }
481 }
482
483 /// <summary>
484 /// Enqueue the MapItem request for remote processing
485 /// </summary>
486 /// <param name="httpserver">blank string, we discover this in the process</param>
487 /// <param name="id">Agent ID that we are making this request on behalf</param>
488 /// <param name="flags">passed in from packet</param>
489 /// <param name="EstateID">passed in from packet</param>
490 /// <param name="godlike">passed in from packet</param>
491 /// <param name="itemtype">passed in from packet</param>
492 /// <param name="regionhandle">Region we're looking up</param>
493 public void RequestMapItems(string httpserver, UUID id, uint flags,
494 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
495 {
496 MapRequestState st = new MapRequestState();
497 st.agentID = id;
498 st.flags = flags;
499 st.EstateID = EstateID;
500 st.godlike = godlike;
501 st.itemtype = itemtype;
502 st.regionhandle = regionhandle;
503 EnqueueMapItemRequest(st);
504 }
505
506 /// <summary>
507 /// Does the actual remote mapitem request
508 /// This should be called from an asynchronous thread
509 /// Request failures get blacklisted until region restart so we don't
510 /// continue to spend resources trying to contact regions that are down.
511 /// </summary>
512 /// <param name="httpserver">blank string, we discover this in the process</param>
513 /// <param name="id">Agent ID that we are making this request on behalf</param>
514 /// <param name="flags">passed in from packet</param>
515 /// <param name="EstateID">passed in from packet</param>
516 /// <param name="godlike">passed in from packet</param>
517 /// <param name="itemtype">passed in from packet</param>
518 /// <param name="regionhandle">Region we're looking up</param>
519 /// <returns></returns>
520 private OSDMap RequestMapItemsAsync(string httpserver, UUID id, uint flags,
521 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
522 {
523 bool blacklisted = false;
524 lock (m_blacklistedregions)
525 {
526 if (m_blacklistedregions.ContainsKey(regionhandle))
527 blacklisted = true;
528 }
529
530 if (blacklisted)
531 return new OSDMap();
532
533 UUID requestID = UUID.Random();
534 lock (m_cachedRegionMapItemsAddress)
535 {
536 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
537 httpserver = m_cachedRegionMapItemsAddress[regionhandle];
538 }
539 if (httpserver.Length == 0)
540 {
541 RegionInfo mreg = m_scene.SceneGridService.RequestNeighbouringRegionInfo(regionhandle);
542
543 if (mreg != null)
544 {
545 httpserver = "http://" + mreg.ExternalEndPoint.Address.ToString() + ":" + mreg.HttpPort + "/MAP/MapItems/" + regionhandle.ToString();
546 lock (m_cachedRegionMapItemsAddress)
547 {
548 if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
549 m_cachedRegionMapItemsAddress.Add(regionhandle, httpserver);
550 }
551 }
552 else
553 {
554 lock (m_blacklistedregions)
555 {
556 if (!m_blacklistedregions.ContainsKey(regionhandle))
557 m_blacklistedregions.Add(regionhandle, System.Environment.TickCount);
558 }
559 m_log.InfoFormat("[WORLD MAP]: Blacklisted region {0}", regionhandle.ToString());
560 }
561 }
562
563 blacklisted = false;
564 lock (m_blacklistedurls)
565 {
566 if (m_blacklistedurls.ContainsKey(httpserver))
567 blacklisted = true;
568 }
569
570 // Can't find the http server
571 if (httpserver.Length == 0 || blacklisted)
572 return new OSDMap();
573
574 MapRequestState mrs = new MapRequestState();
575 mrs.agentID = id;
576 mrs.EstateID = EstateID;
577 mrs.flags = flags;
578 mrs.godlike = godlike;
579 mrs.itemtype=itemtype;
580 mrs.regionhandle = regionhandle;
581
582 lock (m_openRequests)
583 m_openRequests.Add(requestID, mrs);
584
585 WebRequest mapitemsrequest = WebRequest.Create(httpserver);
586 mapitemsrequest.Method = "POST";
587 mapitemsrequest.ContentType = "application/xml+llsd";
588 OSDMap RAMap = new OSDMap();
589
590 // string RAMapString = RAMap.ToString();
591 OSD LLSDofRAMap = RAMap; // RENAME if this works
592
593 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap);
594 OSDMap responseMap = new OSDMap();
595 responseMap["requestID"] = OSD.FromUUID(requestID);
596
597 Stream os = null;
598 try
599 { // send the Post
600 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send
601 os = mapitemsrequest.GetRequestStream();
602 os.Write(buffer, 0, buffer.Length); //Send it
603 os.Close();
604 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from Sim {0}", httpserver);
605 }
606 catch (WebException ex)
607 {
608 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
609 responseMap["connect"] = OSD.FromBoolean(false);
610 lock (m_blacklistedurls)
611 {
612 if (!m_blacklistedurls.ContainsKey(httpserver))
613 m_blacklistedurls.Add(httpserver, System.Environment.TickCount);
614 }
615
616 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
617
618 return responseMap;
619 }
620
621 string response_mapItems_reply = null;
622 { // get the response
623 try
624 {
625 WebResponse webResponse = mapitemsrequest.GetResponse();
626 if (webResponse != null)
627 {
628 StreamReader sr = new StreamReader(webResponse.GetResponseStream());
629 response_mapItems_reply = sr.ReadToEnd().Trim();
630 }
631 else
632 {
633 return new OSDMap();
634 }
635 }
636 catch (WebException)
637 {
638 responseMap["connect"] = OSD.FromBoolean(false);
639 lock (m_blacklistedurls)
640 {
641 if (!m_blacklistedurls.ContainsKey(httpserver))
642 m_blacklistedurls.Add(httpserver, System.Environment.TickCount);
643 }
644
645 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
646
647 return responseMap;
648 }
649 OSD rezResponse = null;
650 try
651 {
652 rezResponse = OSDParser.DeserializeLLSDXml(response_mapItems_reply);
653
654 responseMap = (OSDMap)rezResponse;
655 responseMap["requestID"] = OSD.FromUUID(requestID);
656 }
657 catch (Exception)
658 {
659 //m_log.InfoFormat("[OGP]: exception on parse of rez reply {0}", ex.Message);
660 responseMap["connect"] = OSD.FromBoolean(false);
661
662 return responseMap;
663 }
664 }
665 return responseMap;
666 }
667
668 /// <summary>
669 /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
670 /// </summary>
671 /// <param name="minX"></param>
672 /// <param name="minY"></param>
673 /// <param name="maxX"></param>
674 /// <param name="maxY"></param>
675 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
676 {
677 List<MapBlockData> mapBlocks;
678 if ((flag & 0x10000) != 0) // user clicked on the map a tile that isn't visible
679 {
680 List<MapBlockData> response = new List<MapBlockData>();
681
682 // this should return one mapblock at most. But make sure: Look whether the one we requested is in there
683 mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY);
684 if (mapBlocks != null)
685 {
686 foreach (MapBlockData block in mapBlocks)
687 {
688 if (block.X == minX && block.Y == minY)
689 {
690 // found it => add it to response
691 response.Add(block);
692 break;
693 }
694 }
695 }
696
697 if (response.Count == 0)
698 {
699 // response still empty => couldn't find the map-tile the user clicked on => tell the client
700 MapBlockData block = new MapBlockData();
701 block.X = (ushort)minX;
702 block.Y = (ushort)minY;
703 block.Access = 254; // == not there
704 response.Add(block);
705 }
706 remoteClient.SendMapBlock(response, 0);
707 }
708 else
709 {
710 // normal mapblock request. Use the provided values
711 mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, maxX + 4, maxY + 4);
712 remoteClient.SendMapBlock(mapBlocks, flag);
713 }
714 }
715
716 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
717 {
718 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
719 Hashtable reply = new Hashtable();
720 int statuscode = 200;
721 byte[] jpeg = new byte[0];
722
723 if (myMapImageJPEG.Length == 0)
724 {
725 MemoryStream imgstream = new MemoryStream();
726 Bitmap mapTexture = new Bitmap(1,1);
727 ManagedImage managedImage;
728 Image image = (Image)mapTexture;
729
730 try
731 {
732 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data
733
734 imgstream = new MemoryStream();
735
736 // non-async because we know we have the asset immediately.
737 AssetBase mapasset = m_scene.AssetCache.GetAsset(m_scene.RegionInfo.lastMapUUID, true);
738
739 // Decode image to System.Drawing.Image
740 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image))
741 {
742 // Save to bitmap
743 mapTexture = new Bitmap(image);
744
745 EncoderParameters myEncoderParameters = new EncoderParameters();
746 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
747
748 // Save bitmap to stream
749 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters);
750
751 // Write the stream to a byte array for output
752 jpeg = imgstream.ToArray();
753 myMapImageJPEG = jpeg;
754 }
755 }
756 catch (Exception)
757 {
758 // Dummy!
759 m_log.Warn("[WORLD MAP]: Unable to generate Map image");
760 }
761 finally
762 {
763 // Reclaim memory, these are unmanaged resources
764 mapTexture.Dispose();
765 image.Dispose();
766 imgstream.Close();
767 imgstream.Dispose();
768 }
769 }
770 else
771 {
772 // Use cached version so we don't have to loose our mind
773 jpeg = myMapImageJPEG;
774 }
775
776 reply["str_response_string"] = Convert.ToBase64String(jpeg);
777 reply["int_response_code"] = statuscode;
778 reply["content_type"] = "image/jpeg";
779
780 return reply;
781 }
782
783 // From msdn
784 private static ImageCodecInfo GetEncoderInfo(String mimeType)
785 {
786 ImageCodecInfo[] encoders;
787 encoders = ImageCodecInfo.GetImageEncoders();
788 for (int j = 0; j < encoders.Length; ++j)
789 {
790 if (encoders[j].MimeType == mimeType)
791 return encoders[j];
792 }
793 return null;
794 }
795
796 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
797 {
798 uint xstart = 0;
799 uint ystart = 0;
800
801 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle,out xstart,out ystart);
802
803 OSDMap responsemap = new OSDMap();
804 List<ScenePresence> avatars = m_scene.GetAvatars();
805 OSDArray responsearr = new OSDArray(avatars.Count);
806 OSDMap responsemapdata = new OSDMap();
807 int tc = System.Environment.TickCount;
808 /*
809 foreach (ScenePresence av in avatars)
810 {
811 responsemapdata = new OSDMap();
812 responsemapdata["X"] = OSD.FromInteger((int)(xstart + av.AbsolutePosition.X));
813 responsemapdata["Y"] = OSD.FromInteger((int)(ystart + av.AbsolutePosition.Y));
814 responsemapdata["ID"] = OSD.FromUUID(UUID.Zero);
815 responsemapdata["Name"] = OSD.FromString("TH");
816 responsemapdata["Extra"] = OSD.FromInteger(0);
817 responsemapdata["Extra2"] = OSD.FromInteger(0);
818 responsearr.Add(responsemapdata);
819 }
820 responsemap["1"] = responsearr;
821 */
822 if (avatars.Count == 0)
823 {
824 responsemapdata = new OSDMap();
825 responsemapdata["X"] = OSD.FromInteger((int)(xstart + 1));
826 responsemapdata["Y"] = OSD.FromInteger((int)(ystart + 1));
827 responsemapdata["ID"] = OSD.FromUUID(UUID.Zero);
828 responsemapdata["Name"] = OSD.FromString(Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()));
829 responsemapdata["Extra"] = OSD.FromInteger(0);
830 responsemapdata["Extra2"] = OSD.FromInteger(0);
831 responsearr.Add(responsemapdata);
832
833 responsemap["6"] = responsearr;
834 }
835 else
836 {
837 responsearr = new OSDArray(avatars.Count);
838 foreach (ScenePresence av in avatars)
839 {
840 responsemapdata = new OSDMap();
841 responsemapdata["X"] = OSD.FromInteger((int)(xstart + av.AbsolutePosition.X));
842 responsemapdata["Y"] = OSD.FromInteger((int)(ystart + av.AbsolutePosition.Y));
843 responsemapdata["ID"] = OSD.FromUUID(UUID.Zero);
844 responsemapdata["Name"] = OSD.FromString(Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()));
845 responsemapdata["Extra"] = OSD.FromInteger(1);
846 responsemapdata["Extra2"] = OSD.FromInteger(0);
847 responsearr.Add(responsemapdata);
848 }
849 responsemap["6"] = responsearr;
850 }
851 return responsemap;
852 }
853
854 private void MakeRootAgent(ScenePresence avatar)
855 {
856 // You may ask, why this is in a threadpool to start with..
857 // The reason is so we don't cause the thread to freeze waiting
858 // for the 1 second it costs to start a thread manually.
859 if (!threadrunning)
860 ThreadPool.QueueUserWorkItem(new WaitCallback(this.StartThread));
861
862 lock (m_rootAgents)
863 {
864 if (!m_rootAgents.Contains(avatar.UUID))
865 {
866 m_rootAgents.Add(avatar.UUID);
867 }
868 }
869 }
870
871 private void MakeChildAgent(ScenePresence avatar)
872 {
873 List<ScenePresence> presences = m_scene.GetAvatars();
874 int rootcount = 0;
875 for (int i = 0; i < presences.Count; i++)
876 {
877 if (presences[i] != null)
878 {
879 if (!presences[i].IsChildAgent)
880 rootcount++;
881 }
882 }
883 if (rootcount <= 1)
884 StopThread();
885
886 lock (m_rootAgents)
887 {
888 if (m_rootAgents.Contains(avatar.UUID))
889 {
890 m_rootAgents.Remove(avatar.UUID);
891 }
892 }
893 }
894 }
895
896 public struct MapRequestState
897 {
898 public UUID agentID;
899 public uint flags;
900 public uint EstateID;
901 public bool godlike;
902 public uint itemtype;
903 public ulong regionhandle;
904 }
905}