clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Collections.Generic;
30 using System.Reflection;
31 using log4net;
32 using Nini.Config;
33 using OpenMetaverse;
34 using OpenSim.Framework;
35 using OpenSim.Framework.Client;
36 using OpenSim.Region.Framework.Interfaces;
37 using OpenSim.Region.Framework.Scenes;
38 using OpenSim.Framework.Console;
39 using OpenSim.Region.Physics.Manager;
40 using Mono.Addins;
41  
42 namespace OpenSim.Region.RegionCombinerModule
43 {
44 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 // private static string LogHeader = "[REGION COMBINER MODULE]";
48  
49 public string Name
50 {
51 get { return "RegionCombinerModule"; }
52 }
53  
54 public Type ReplaceableInterface
55 {
56 get { return null; }
57 }
58  
59 /// <summary>
60 /// Is this module enabled?
61 /// </summary>
62 private bool m_combineContiguousRegions = false;
63  
64 /// <summary>
65 /// This holds the root regions for the megaregions.
66 /// </summary>
67 /// <remarks>
68 /// Usually there is only ever one megaregion (and hence only one entry here).
69 /// </remarks>
70 private Dictionary<UUID, RegionConnections> m_regions = new Dictionary<UUID, RegionConnections>();
71  
72 /// <summary>
73 /// The scenes that comprise the megaregion.
74 /// </summary>
75 private Dictionary<UUID, Scene> m_startingScenes = new Dictionary<UUID, Scene>();
76  
77 public void Initialise(IConfigSource source)
78 {
79 IConfig myConfig = source.Configs["Startup"];
80 m_combineContiguousRegions = myConfig.GetBoolean("CombineContiguousRegions", false);
81  
82 MainConsole.Instance.Commands.AddCommand(
83 "RegionCombinerModule", false, "fix-phantoms", "fix-phantoms",
84 "Fixes phantom objects after an import to a megaregion or a change from a megaregion back to normal regions",
85 FixPhantoms);
86 }
87  
88 public void Close()
89 {
90 }
91  
92 public void AddRegion(Scene scene)
93 {
94 if (m_combineContiguousRegions)
95 scene.RegisterModuleInterface<IRegionCombinerModule>(this);
96 }
97  
98 public void RemoveRegion(Scene scene)
99 {
100 lock (m_startingScenes)
101 m_startingScenes.Remove(scene.RegionInfo.originRegionID);
102 }
103  
104 public void RegionLoaded(Scene scene)
105 {
106 lock (m_startingScenes)
107 m_startingScenes.Add(scene.RegionInfo.originRegionID, scene);
108  
109 if (m_combineContiguousRegions)
110 {
111 RegionLoadedDoWork(scene);
112  
113 scene.EventManager.OnNewPresence += NewPresence;
114 }
115 }
116  
117 public bool IsRootForMegaregion(UUID regionId)
118 {
119 lock (m_regions)
120 return m_regions.ContainsKey(regionId);
121 }
122  
123 public Vector2 GetSizeOfMegaregion(UUID regionId)
124 {
125 lock (m_regions)
126 {
127 if (m_regions.ContainsKey(regionId))
128 {
129 RegionConnections rootConn = m_regions[regionId];
130  
131 return new Vector2((float)rootConn.XEnd, (float)rootConn.YEnd);
132 }
133 }
134  
135 throw new Exception(string.Format("Region with id {0} not found", regionId));
136 }
137  
138 // Test to see if this postiion (relative to the region) is within the area covered
139 // by this megaregion.
140 public bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy)
141 {
142 bool ret = false;
143 if (xx < 0 || yy < 0)
144 return ret;
145  
146 foreach (RegionConnections rootRegion in m_regions.Values)
147 {
148 if (currentRegion == rootRegion.RegionId)
149 {
150 // The caller is in the root region so this is an easy test
151 if (xx < rootRegion.XEnd && yy < rootRegion.YEnd)
152 {
153 ret = true;
154 }
155 break;
156 }
157 else
158 {
159 // Maybe the caller is in one of the sub-regions
160 foreach (RegionData childRegion in rootRegion.ConnectedRegions)
161 {
162 if (currentRegion == childRegion.RegionId)
163 {
164 // This is a child. Diddle the offsets and check if in
165 Vector3 positionInMegaregion = childRegion.Offset;
166 positionInMegaregion.X += xx;
167 positionInMegaregion.Y += yy;
168 if (positionInMegaregion.X < rootRegion.XEnd && positionInMegaregion.Y < rootRegion.YEnd)
169 {
170 ret = true;
171 }
172 break;
173 }
174 }
175 }
176 }
177  
178 return ret;
179 }
180  
181 private void NewPresence(ScenePresence presence)
182 {
183 if (presence.IsChildAgent)
184 {
185 byte[] throttleData;
186  
187 try
188 {
189 throttleData = presence.ControllingClient.GetThrottlesPacked(1);
190 }
191 catch (NotImplementedException)
192 {
193 return;
194 }
195  
196 if (throttleData == null)
197 return;
198  
199 if (throttleData.Length == 0)
200 return;
201  
202 if (throttleData.Length != 28)
203 return;
204  
205 byte[] adjData;
206 int pos = 0;
207  
208 if (!BitConverter.IsLittleEndian)
209 {
210 byte[] newData = new byte[7 * 4];
211 Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4);
212  
213 for (int i = 0; i < 7; i++)
214 Array.Reverse(newData, i * 4, 4);
215  
216 adjData = newData;
217 }
218 else
219 {
220 adjData = throttleData;
221 }
222  
223 // 0.125f converts from bits to bytes
224 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
225 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
226 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
227 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
228 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
229 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
230 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
231 // State is a subcategory of task that we allocate a percentage to
232  
233  
234 //int total = resend + land + wind + cloud + task + texture + asset;
235  
236 byte[] data = new byte[7 * 4];
237 int ii = 0;
238  
239 Buffer.BlockCopy(Utils.FloatToBytes(resend), 0, data, ii, 4); ii += 4;
240 Buffer.BlockCopy(Utils.FloatToBytes(land * 50), 0, data, ii, 4); ii += 4;
241 Buffer.BlockCopy(Utils.FloatToBytes(wind), 0, data, ii, 4); ii += 4;
242 Buffer.BlockCopy(Utils.FloatToBytes(cloud), 0, data, ii, 4); ii += 4;
243 Buffer.BlockCopy(Utils.FloatToBytes(task), 0, data, ii, 4); ii += 4;
244 Buffer.BlockCopy(Utils.FloatToBytes(texture), 0, data, ii, 4); ii += 4;
245 Buffer.BlockCopy(Utils.FloatToBytes(asset), 0, data, ii, 4);
246  
247 try
248 {
249 presence.ControllingClient.SetChildAgentThrottle(data);
250 }
251 catch (NotImplementedException)
252 {
253 return;
254 }
255 }
256 }
257  
258 private void RegionLoadedDoWork(Scene scene)
259 {
260 /*
261 // For testing on a single instance
262 if (scene.RegionInfo.RegionLocX == 1004 && scene.RegionInfo.RegionLocY == 1000)
263 return;
264 //
265 */
266  
267 RegionConnections newConn = new RegionConnections();
268 newConn.ConnectedRegions = new List<RegionData>();
269 newConn.RegionScene = scene;
270 newConn.RegionLandChannel = scene.LandChannel;
271 newConn.RegionId = scene.RegionInfo.originRegionID;
272 newConn.X = scene.RegionInfo.RegionLocX;
273 newConn.Y = scene.RegionInfo.RegionLocY;
274 newConn.XEnd = scene.RegionInfo.RegionSizeX;
275 newConn.YEnd = scene.RegionInfo.RegionSizeX;
276  
277 lock (m_regions)
278 {
279 bool connectedYN = false;
280  
281 foreach (RegionConnections rootConn in m_regions.Values)
282 {
283 #region commented
284 /*
285 // If we're one region over +x +y
286 //xxy
287 //xxx
288 //xxx
289 if ((((int)conn.X * (int)Constants.RegionSize) + conn.XEnd
290 == (regionConnections.X * (int)Constants.RegionSize))
291 && (((int)conn.Y * (int)Constants.RegionSize) - conn.YEnd
292 == (regionConnections.Y * (int)Constants.RegionSize)))
293 {
294 Vector3 offset = Vector3.Zero;
295 offset.X = (((regionConnections.X * (int) Constants.RegionSize)) -
296 ((conn.X * (int) Constants.RegionSize)));
297 offset.Y = (((regionConnections.Y * (int) Constants.RegionSize)) -
298 ((conn.Y * (int) Constants.RegionSize)));
299  
300 Vector3 extents = Vector3.Zero;
301 extents.Y = regionConnections.YEnd + conn.YEnd;
302 extents.X = conn.XEnd + conn.XEnd;
303  
304 m_log.DebugFormat("Scene: {0} to the northwest of Scene{1}. Offset: {2}. Extents:{3}",
305 conn.RegionScene.RegionInfo.RegionName,
306 regionConnections.RegionScene.RegionInfo.RegionName,
307 offset, extents);
308  
309 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
310  
311 connectedYN = true;
312 break;
313 }
314 */
315  
316 /*
317 //If we're one region over x +y
318 //xxx
319 //xxx
320 //xyx
321 if ((((int)conn.X * (int)Constants.RegionSize)
322 == (regionConnections.X * (int)Constants.RegionSize))
323 && (((int)conn.Y * (int)Constants.RegionSize) - conn.YEnd
324 == (regionConnections.Y * (int)Constants.RegionSize)))
325 {
326 Vector3 offset = Vector3.Zero;
327 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
328 ((conn.X * (int)Constants.RegionSize)));
329 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
330 ((conn.Y * (int)Constants.RegionSize)));
331  
332 Vector3 extents = Vector3.Zero;
333 extents.Y = regionConnections.YEnd + conn.YEnd;
334 extents.X = conn.XEnd;
335  
336 m_log.DebugFormat("Scene: {0} to the north of Scene{1}. Offset: {2}. Extents:{3}",
337 conn.RegionScene.RegionInfo.RegionName,
338 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
339  
340 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
341 connectedYN = true;
342 break;
343 }
344 */
345  
346 /*
347 // If we're one region over -x +y
348 //xxx
349 //xxx
350 //yxx
351 if ((((int)conn.X * (int)Constants.RegionSize) - conn.XEnd
352 == (regionConnections.X * (int)Constants.RegionSize))
353 && (((int)conn.Y * (int)Constants.RegionSize) - conn.YEnd
354 == (regionConnections.Y * (int)Constants.RegionSize)))
355 {
356 Vector3 offset = Vector3.Zero;
357 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
358 ((conn.X * (int)Constants.RegionSize)));
359 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
360 ((conn.Y * (int)Constants.RegionSize)));
361  
362 Vector3 extents = Vector3.Zero;
363 extents.Y = regionConnections.YEnd + conn.YEnd;
364 extents.X = conn.XEnd + conn.XEnd;
365  
366 m_log.DebugFormat("Scene: {0} to the northeast of Scene. Offset: {2}. Extents:{3}",
367 conn.RegionScene.RegionInfo.RegionName,
368 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
369  
370 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
371  
372  
373 connectedYN = true;
374 break;
375 }
376 */
377  
378 /*
379 // If we're one region over -x y
380 //xxx
381 //yxx
382 //xxx
383 if ((((int)conn.X * (int)Constants.RegionSize) - conn.XEnd
384 == (regionConnections.X * (int)Constants.RegionSize))
385 && (((int)conn.Y * (int)Constants.RegionSize)
386 == (regionConnections.Y * (int)Constants.RegionSize)))
387 {
388 Vector3 offset = Vector3.Zero;
389 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
390 ((conn.X * (int)Constants.RegionSize)));
391 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
392 ((conn.Y * (int)Constants.RegionSize)));
393  
394 Vector3 extents = Vector3.Zero;
395 extents.Y = regionConnections.YEnd;
396 extents.X = conn.XEnd + conn.XEnd;
397  
398 m_log.DebugFormat("Scene: {0} to the east of Scene{1} Offset: {2}. Extents:{3}",
399 conn.RegionScene.RegionInfo.RegionName,
400 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
401  
402 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
403  
404 connectedYN = true;
405 break;
406 }
407 */
408  
409 /*
410 // If we're one region over -x -y
411 //yxx
412 //xxx
413 //xxx
414 if ((((int)conn.X * (int)Constants.RegionSize) - conn.XEnd
415 == (regionConnections.X * (int)Constants.RegionSize))
416 && (((int)conn.Y * (int)Constants.RegionSize) + conn.YEnd
417 == (regionConnections.Y * (int)Constants.RegionSize)))
418 {
419 Vector3 offset = Vector3.Zero;
420 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
421 ((conn.X * (int)Constants.RegionSize)));
422 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
423 ((conn.Y * (int)Constants.RegionSize)));
424  
425 Vector3 extents = Vector3.Zero;
426 extents.Y = regionConnections.YEnd + conn.YEnd;
427 extents.X = conn.XEnd + conn.XEnd;
428  
429 m_log.DebugFormat("Scene: {0} to the northeast of Scene{1} Offset: {2}. Extents:{3}",
430 conn.RegionScene.RegionInfo.RegionName,
431 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
432  
433 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
434  
435 connectedYN = true;
436 break;
437 }
438 */
439 #endregion
440  
441  
442 // Check to see if this new region is adjacent to the root region.
443 // Note that we expect the regions to be combined from the root region outward
444 // thus the requirement for the ordering in the configuration files.
445  
446 // If we're one region over +x y (i.e. root region is to the west)
447 //xxx
448 //xxy
449 //xxx
450 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY)
451 {
452 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
453 break;
454 }
455  
456 // If we're one region over x +y (i.e. root region is to the south)
457 //xyx
458 //xxx
459 //xxx
460 if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
461 {
462 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
463 break;
464 }
465  
466 // If we're one region over +x +y (i.e. root region is to the south-west)
467 //xxy
468 //xxx
469 //xxx
470 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
471 {
472 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
473 break;
474 }
475 }
476  
477 // If !connectYN means that this region is a root region
478 if (!connectedYN)
479 {
480 DoWorkForRootRegion(newConn, scene);
481 }
482 }
483 }
484  
485 private bool DoWorkForOneRegionOverPlusXY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
486 {
487 // Offset (in meters) from the base of this region to the base of the root region.
488 Vector3 offset = Vector3.Zero;
489 offset.X = newConn.PosX - rootConn.PosX;
490 offset.Y = newConn.PosY - rootConn.PosY;
491  
492 // The new total size of the region (in meters)
493 // We just extend the X and Y dimensions so the extent might temporarily include areas without regions.
494 Vector3 extents = Vector3.Zero;
495 extents.X = Math.Max(rootConn.XEnd, offset.X + newConn.RegionScene.RegionInfo.RegionSizeX);
496 extents.Y = Math.Max(rootConn.YEnd, offset.Y + newConn.RegionScene.RegionInfo.RegionSizeY);
497  
498 rootConn.UpdateExtents(extents);
499  
500 m_log.DebugFormat(
501 "[REGION COMBINER MODULE]: Root region {0} is to the west of region {1}, Offset: {2}, Extents: {3}",
502 rootConn.RegionScene.RegionInfo.RegionName,
503 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
504  
505 RegionData ConnectedRegion = new RegionData();
506 ConnectedRegion.Offset = offset;
507 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
508 ConnectedRegion.RegionScene = scene;
509 rootConn.ConnectedRegions.Add(ConnectedRegion);
510  
511 // Inform root region Physics about the extents of this region
512 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
513  
514 // Inform Child region that it needs to forward it's terrain to the root region
515 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
516  
517 // Reset Terrain.. since terrain loads before we get here, we need to load
518 // it again so it loads in the root region
519 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
520  
521 // Create a client event forwarder and add this region's events to the root region.
522 if (rootConn.ClientEventForwarder != null)
523 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
524  
525 return true;
526 }
527  
528 /*
529 * 20140215 radams1: The border stuff was removed and the addition of regions to the mega-regions
530 * was generalized. These functions are not needed for the generalized solution but left for reference.
531 private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
532 {
533 Vector3 offset = Vector3.Zero;
534 offset.X = newConn.PosX - rootConn.PosX;
535 offset.Y = newConn.PosY - rootConn.PosY;
536  
537 Vector3 extents = Vector3.Zero;
538 extents.Y = newConn.YEnd + rootConn.YEnd;
539 extents.X = rootConn.XEnd;
540 rootConn.UpdateExtents(extents);
541  
542 RegionData ConnectedRegion = new RegionData();
543 ConnectedRegion.Offset = offset;
544 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
545 ConnectedRegion.RegionScene = scene;
546 rootConn.ConnectedRegions.Add(ConnectedRegion);
547  
548 m_log.DebugFormat(
549 "[REGION COMBINER MODULE]: Root region {0} is to the south of region {1}, Offset: {2}, Extents: {3}",
550 rootConn.RegionScene.RegionInfo.RegionName,
551 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
552  
553 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
554 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
555  
556 // Reset Terrain.. since terrain normally loads first.
557 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
558 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
559 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
560  
561 if (rootConn.ClientEventForwarder != null)
562 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
563  
564 return true;
565 }
566  
567 private bool DoWorkForOneRegionOverPlusXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
568 {
569 Vector3 offset = Vector3.Zero;
570 offset.X = newConn.PosX - rootConn.PosX;
571 offset.Y = newConn.PosY - rootConn.PosY;
572  
573 Vector3 extents = Vector3.Zero;
574  
575 // We do not want to inflate the extents for regions strictly to the NE of the root region, since this
576 // would double count regions strictly to the north and east that have already been added.
577 // extents.Y = regionConnections.YEnd + conn.YEnd;
578 // extents.X = regionConnections.XEnd + conn.XEnd;
579 // conn.UpdateExtents(extents);
580  
581 extents.Y = rootConn.YEnd;
582 extents.X = rootConn.XEnd;
583  
584 RegionData ConnectedRegion = new RegionData();
585 ConnectedRegion.Offset = offset;
586 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
587 ConnectedRegion.RegionScene = scene;
588  
589 rootConn.ConnectedRegions.Add(ConnectedRegion);
590  
591 m_log.DebugFormat(
592 "[REGION COMBINER MODULE]: Region {0} is to the southwest of Scene {1}, Offset: {2}, Extents: {3}",
593 rootConn.RegionScene.RegionInfo.RegionName,
594 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
595  
596 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
597 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
598  
599 // Reset Terrain.. since terrain normally loads first.
600 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
601 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
602 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
603  
604 if (rootConn.ClientEventForwarder != null)
605 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
606  
607 return true;
608  
609 //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
610 }
611 */
612  
613 private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene)
614 {
615 m_log.DebugFormat("[REGION COMBINER MODULE]: Adding root region {0}", scene.RegionInfo.RegionName);
616  
617 RegionData rdata = new RegionData();
618 rdata.Offset = Vector3.Zero;
619 rdata.RegionId = scene.RegionInfo.originRegionID;
620 rdata.RegionScene = scene;
621 // save it's land channel
622 rootConn.RegionLandChannel = scene.LandChannel;
623  
624 // Substitue our landchannel
625 RegionCombinerLargeLandChannel lnd = new RegionCombinerLargeLandChannel(rdata, scene.LandChannel,
626 rootConn.ConnectedRegions);
627  
628 scene.LandChannel = lnd;
629  
630 // Forward the permissions modules of each of the connected regions to the root region
631 lock (m_regions)
632 {
633 foreach (RegionData r in rootConn.ConnectedRegions)
634 {
635 ForwardPermissionRequests(rootConn, r.RegionScene);
636 }
637  
638 // Create the root region's Client Event Forwarder
639 rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn);
640  
641 // Sets up the CoarseLocationUpdate forwarder for this root region
642 scene.EventManager.OnNewPresence += SetCoarseLocationDelegate;
643  
644 // Adds this root region to a dictionary of regions that are connectable
645 m_regions.Add(scene.RegionInfo.originRegionID, rootConn);
646 }
647 }
648  
649 private void SetCoarseLocationDelegate(ScenePresence presence)
650 {
651 presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates);
652 }
653  
654 // This delegate was refactored for non-combined regions.
655 // This combined region version will not use the pre-compiled lists of locations and ids
656 private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
657 {
658 RegionConnections connectiondata = null;
659 lock (m_regions)
660 {
661 if (m_regions.ContainsKey(sceneId))
662 connectiondata = m_regions[sceneId];
663 else
664 return;
665 }
666  
667 List<Vector3> CoarseLocations = new List<Vector3>();
668 List<UUID> AvatarUUIDs = new List<UUID>();
669  
670 connectiondata.RegionScene.ForEachRootScenePresence(delegate(ScenePresence sp)
671 {
672 if (sp.UUID != presence.UUID)
673 {
674 CoarseLocations.Add(sp.AbsolutePosition);
675 AvatarUUIDs.Add(sp.UUID);
676 }
677 });
678  
679 DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence);
680 }
681  
682 private void DistributeCoarseLocationUpdates(List<Vector3> locations, List<UUID> uuids,
683 RegionConnections connectiondata, ScenePresence rootPresence)
684 {
685 RegionData[] rdata = connectiondata.ConnectedRegions.ToArray();
686 //List<IClientAPI> clients = new List<IClientAPI>();
687 Dictionary<Vector2, RegionCoarseLocationStruct> updates = new Dictionary<Vector2, RegionCoarseLocationStruct>();
688  
689 // Root Region entry
690 RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct();
691 rootupdatedata.Locations = new List<Vector3>();
692 rootupdatedata.Uuids = new List<UUID>();
693 rootupdatedata.Offset = Vector2.Zero;
694  
695 rootupdatedata.UserAPI = rootPresence.ControllingClient;
696  
697 if (rootupdatedata.UserAPI != null)
698 updates.Add(Vector2.Zero, rootupdatedata);
699  
700 //Each Region needs an entry or we will end up with dead minimap dots
701 foreach (RegionData regiondata in rdata)
702 {
703 Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y);
704 RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct();
705 updatedata.Locations = new List<Vector3>();
706 updatedata.Uuids = new List<UUID>();
707 updatedata.Offset = offset;
708  
709 if (offset == Vector2.Zero)
710 updatedata.UserAPI = rootPresence.ControllingClient;
711 else
712 updatedata.UserAPI = LocateUsersChildAgentIClientAPI(offset, rootPresence.UUID, rdata);
713  
714 if (updatedata.UserAPI != null)
715 updates.Add(offset, updatedata);
716 }
717  
718 // go over the locations and assign them to an IClientAPI
719 for (int i = 0; i < locations.Count; i++)
720 //{locations[i]/(int) Constants.RegionSize;
721 {
722 Vector3 pPosition = new Vector3((int)locations[i].X / (int)Constants.RegionSize,
723 (int)locations[i].Y / (int)Constants.RegionSize, locations[i].Z);
724 Vector2 offset = new Vector2(pPosition.X*(int) Constants.RegionSize,
725 pPosition.Y*(int) Constants.RegionSize);
726  
727 if (!updates.ContainsKey(offset))
728 {
729 // This shouldn't happen
730 RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct();
731 updatedata.Locations = new List<Vector3>();
732 updatedata.Uuids = new List<UUID>();
733 updatedata.Offset = offset;
734  
735 if (offset == Vector2.Zero)
736 updatedata.UserAPI = rootPresence.ControllingClient;
737 else
738 updatedata.UserAPI = LocateUsersChildAgentIClientAPI(offset, rootPresence.UUID, rdata);
739  
740 updates.Add(offset,updatedata);
741 }
742  
743 updates[offset].Locations.Add(locations[i]);
744 updates[offset].Uuids.Add(uuids[i]);
745 }
746  
747 // Send out the CoarseLocationupdates from their respective client connection based on where the avatar is
748 foreach (Vector2 offset in updates.Keys)
749 {
750 if (updates[offset].UserAPI != null)
751 {
752 updates[offset].UserAPI.SendCoarseLocationUpdate(updates[offset].Uuids,updates[offset].Locations);
753 }
754 }
755 }
756  
757 /// <summary>
758 /// Locates a the Client of a particular region in an Array of RegionData based on offset
759 /// </summary>
760 /// <param name="offset"></param>
761 /// <param name="uUID"></param>
762 /// <param name="rdata"></param>
763 /// <returns>IClientAPI or null</returns>
764 private IClientAPI LocateUsersChildAgentIClientAPI(Vector2 offset, UUID uUID, RegionData[] rdata)
765 {
766 IClientAPI returnclient = null;
767 foreach (RegionData r in rdata)
768 {
769 if (r.Offset.X == offset.X && r.Offset.Y == offset.Y)
770 {
771 return r.RegionScene.SceneGraph.GetControllingClient(uUID);
772 }
773 }
774  
775 return returnclient;
776 }
777  
778 public void PostInitialise()
779 {
780 }
781  
782 // /// <summary>
783 // /// TODO:
784 // /// </summary>
785 // /// <param name="rdata"></param>
786 // public void UnCombineRegion(RegionData rdata)
787 // {
788 // lock (m_regions)
789 // {
790 // if (m_regions.ContainsKey(rdata.RegionId))
791 // {
792 // // uncombine root region and virtual regions
793 // }
794 // else
795 // {
796 // foreach (RegionConnections r in m_regions.Values)
797 // {
798 // foreach (RegionData rd in r.ConnectedRegions)
799 // {
800 // if (rd.RegionId == rdata.RegionId)
801 // {
802 // // uncombine virtual region
803 // }
804 // }
805 // }
806 // }
807 // }
808 // }
809  
810 public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion)
811 {
812 if (BigRegion.PermissionModule == null)
813 BigRegion.PermissionModule = new RegionCombinerPermissionModule(BigRegion.RegionScene);
814  
815 VirtualRegion.Permissions.OnBypassPermissions += BigRegion.PermissionModule.BypassPermissions;
816 VirtualRegion.Permissions.OnSetBypassPermissions += BigRegion.PermissionModule.SetBypassPermissions;
817 VirtualRegion.Permissions.OnPropagatePermissions += BigRegion.PermissionModule.PropagatePermissions;
818 VirtualRegion.Permissions.OnGenerateClientFlags += BigRegion.PermissionModule.GenerateClientFlags;
819 VirtualRegion.Permissions.OnAbandonParcel += BigRegion.PermissionModule.CanAbandonParcel;
820 VirtualRegion.Permissions.OnReclaimParcel += BigRegion.PermissionModule.CanReclaimParcel;
821 VirtualRegion.Permissions.OnDeedParcel += BigRegion.PermissionModule.CanDeedParcel;
822 VirtualRegion.Permissions.OnDeedObject += BigRegion.PermissionModule.CanDeedObject;
823 VirtualRegion.Permissions.OnIsGod += BigRegion.PermissionModule.IsGod;
824 VirtualRegion.Permissions.OnDuplicateObject += BigRegion.PermissionModule.CanDuplicateObject;
825 VirtualRegion.Permissions.OnDeleteObject += BigRegion.PermissionModule.CanDeleteObject; //MAYBE FULLY IMPLEMENTED
826 VirtualRegion.Permissions.OnEditObject += BigRegion.PermissionModule.CanEditObject; //MAYBE FULLY IMPLEMENTED
827 VirtualRegion.Permissions.OnEditParcelProperties += BigRegion.PermissionModule.CanEditParcelProperties; //MAYBE FULLY IMPLEMENTED
828 VirtualRegion.Permissions.OnInstantMessage += BigRegion.PermissionModule.CanInstantMessage;
829 VirtualRegion.Permissions.OnInventoryTransfer += BigRegion.PermissionModule.CanInventoryTransfer; //NOT YET IMPLEMENTED
830 VirtualRegion.Permissions.OnIssueEstateCommand += BigRegion.PermissionModule.CanIssueEstateCommand; //FULLY IMPLEMENTED
831 VirtualRegion.Permissions.OnMoveObject += BigRegion.PermissionModule.CanMoveObject; //MAYBE FULLY IMPLEMENTED
832 VirtualRegion.Permissions.OnObjectEntry += BigRegion.PermissionModule.CanObjectEntry;
833 VirtualRegion.Permissions.OnReturnObjects += BigRegion.PermissionModule.CanReturnObjects; //NOT YET IMPLEMENTED
834 VirtualRegion.Permissions.OnRezObject += BigRegion.PermissionModule.CanRezObject; //MAYBE FULLY IMPLEMENTED
835 VirtualRegion.Permissions.OnRunConsoleCommand += BigRegion.PermissionModule.CanRunConsoleCommand;
836 VirtualRegion.Permissions.OnRunScript += BigRegion.PermissionModule.CanRunScript; //NOT YET IMPLEMENTED
837 VirtualRegion.Permissions.OnCompileScript += BigRegion.PermissionModule.CanCompileScript;
838 VirtualRegion.Permissions.OnSellParcel += BigRegion.PermissionModule.CanSellParcel;
839 VirtualRegion.Permissions.OnTakeObject += BigRegion.PermissionModule.CanTakeObject;
840 VirtualRegion.Permissions.OnTakeCopyObject += BigRegion.PermissionModule.CanTakeCopyObject;
841 VirtualRegion.Permissions.OnTerraformLand += BigRegion.PermissionModule.CanTerraformLand;
842 VirtualRegion.Permissions.OnLinkObject += BigRegion.PermissionModule.CanLinkObject; //NOT YET IMPLEMENTED
843 VirtualRegion.Permissions.OnDelinkObject += BigRegion.PermissionModule.CanDelinkObject; //NOT YET IMPLEMENTED
844 VirtualRegion.Permissions.OnBuyLand += BigRegion.PermissionModule.CanBuyLand; //NOT YET IMPLEMENTED
845 VirtualRegion.Permissions.OnViewNotecard += BigRegion.PermissionModule.CanViewNotecard; //NOT YET IMPLEMENTED
846 VirtualRegion.Permissions.OnViewScript += BigRegion.PermissionModule.CanViewScript; //NOT YET IMPLEMENTED
847 VirtualRegion.Permissions.OnEditNotecard += BigRegion.PermissionModule.CanEditNotecard; //NOT YET IMPLEMENTED
848 VirtualRegion.Permissions.OnEditScript += BigRegion.PermissionModule.CanEditScript; //NOT YET IMPLEMENTED
849 VirtualRegion.Permissions.OnCreateObjectInventory += BigRegion.PermissionModule.CanCreateObjectInventory; //NOT IMPLEMENTED HERE
850 VirtualRegion.Permissions.OnEditObjectInventory += BigRegion.PermissionModule.CanEditObjectInventory;//MAYBE FULLY IMPLEMENTED
851 VirtualRegion.Permissions.OnCopyObjectInventory += BigRegion.PermissionModule.CanCopyObjectInventory; //NOT YET IMPLEMENTED
852 VirtualRegion.Permissions.OnDeleteObjectInventory += BigRegion.PermissionModule.CanDeleteObjectInventory; //NOT YET IMPLEMENTED
853 VirtualRegion.Permissions.OnResetScript += BigRegion.PermissionModule.CanResetScript;
854 VirtualRegion.Permissions.OnCreateUserInventory += BigRegion.PermissionModule.CanCreateUserInventory; //NOT YET IMPLEMENTED
855 VirtualRegion.Permissions.OnCopyUserInventory += BigRegion.PermissionModule.CanCopyUserInventory; //NOT YET IMPLEMENTED
856 VirtualRegion.Permissions.OnEditUserInventory += BigRegion.PermissionModule.CanEditUserInventory; //NOT YET IMPLEMENTED
857 VirtualRegion.Permissions.OnDeleteUserInventory += BigRegion.PermissionModule.CanDeleteUserInventory; //NOT YET IMPLEMENTED
858 VirtualRegion.Permissions.OnTeleport += BigRegion.PermissionModule.CanTeleport; //NOT YET IMPLEMENTED
859 }
860  
861 #region console commands
862  
863 public void FixPhantoms(string module, string[] cmdparams)
864 {
865 List<Scene> scenes = new List<Scene>(m_startingScenes.Values);
866  
867 foreach (Scene s in scenes)
868 {
869 MainConsole.Instance.OutputFormat("Fixing phantoms for {0}", s.RegionInfo.RegionName);
870  
871 s.ForEachSOG(so => so.AbsolutePosition = so.AbsolutePosition);
872 }
873 }
874  
875 #endregion
876 }
877 }