ArchiveScenesGroup.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. using System;
  28. using System.Collections.Generic;
  29. using System.Linq;
  30. using System.Text;
  31. using OpenSim.Region.Framework.Scenes;
  32. using OpenMetaverse;
  33. using System.Drawing;
  34. namespace OpenSim.Region.CoreModules.World.Archiver
  35. {
  36. /// <summary>
  37. /// A group of regions arranged in a rectangle, possibly with holes.
  38. /// </summary>
  39. /// <remarks>
  40. /// The regions usually (but not necessarily) belong to an archive file, in which case we
  41. /// store additional information used to create the archive (e.g., each region's
  42. /// directory within the archive).
  43. /// </remarks>
  44. public class ArchiveScenesGroup
  45. {
  46. /// <summary>
  47. /// All the regions. The outer dictionary contains rows (key: Y coordinate).
  48. /// The inner dictionaries contain each row's regions (key: X coordinate).
  49. /// </summary>
  50. public SortedDictionary<uint, SortedDictionary<uint, Scene>> Regions { get; set; }
  51. /// <summary>
  52. /// The subdirectory where each region is stored in the archive.
  53. /// </summary>
  54. protected Dictionary<UUID, string> m_regionDirs;
  55. /// <summary>
  56. /// The grid coordinates of the regions' bounding box.
  57. /// </summary>
  58. public Rectangle Rect { get; set; }
  59. public ArchiveScenesGroup()
  60. {
  61. Regions = new SortedDictionary<uint, SortedDictionary<uint, Scene>>();
  62. m_regionDirs = new Dictionary<UUID, string>();
  63. Rect = new Rectangle(0, 0, 0, 0);
  64. }
  65. public void AddScene(Scene scene)
  66. {
  67. uint x = scene.RegionInfo.RegionLocX;
  68. uint y = scene.RegionInfo.RegionLocY;
  69. SortedDictionary<uint, Scene> row;
  70. if (!Regions.TryGetValue(y, out row))
  71. {
  72. row = new SortedDictionary<uint, Scene>();
  73. Regions[y] = row;
  74. }
  75. row[x] = scene;
  76. }
  77. /// <summary>
  78. /// Called after all the scenes have been added. Performs calculations that require
  79. /// knowledge of all the scenes.
  80. /// </summary>
  81. public void CalcSceneLocations()
  82. {
  83. if (Regions.Count == 0)
  84. return;
  85. // Find the bounding rectangle
  86. uint firstY = Regions.First().Key;
  87. uint lastY = Regions.Last().Key;
  88. uint? firstX = null;
  89. uint? lastX = null;
  90. foreach (SortedDictionary<uint, Scene> row in Regions.Values)
  91. {
  92. uint curFirstX = row.First().Key;
  93. uint curLastX = row.Last().Key;
  94. firstX = (firstX == null) ? curFirstX : (firstX < curFirstX) ? firstX : curFirstX;
  95. lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX;
  96. }
  97. Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastX - firstX + 1), (int)(lastY - firstY + 1));
  98. // Calculate the subdirectory in which each region will be stored in the archive
  99. m_regionDirs.Clear();
  100. ForEachScene(delegate(Scene scene)
  101. {
  102. // We add the region's coordinates to ensure uniqueness even if multiple regions have the same name
  103. string path = string.Format("{0}_{1}_{2}",
  104. scene.RegionInfo.RegionLocX - Rect.X + 1,
  105. scene.RegionInfo.RegionLocY - Rect.Y + 1,
  106. scene.RegionInfo.RegionName.Replace(' ', '_'));
  107. m_regionDirs[scene.RegionInfo.RegionID] = path;
  108. });
  109. }
  110. /// <summary>
  111. /// Returns the subdirectory where the region is stored.
  112. /// </summary>
  113. /// <param name="regionID"></param>
  114. /// <returns></returns>
  115. public string GetRegionDir(UUID regionID)
  116. {
  117. return m_regionDirs[regionID];
  118. }
  119. /// <summary>
  120. /// Performs an action on all the scenes in this order: rows from South to North,
  121. /// and within each row West to East.
  122. /// </summary>
  123. /// <param name="action"></param>
  124. public void ForEachScene(Action<Scene> action)
  125. {
  126. foreach (SortedDictionary<uint, Scene> row in Regions.Values)
  127. {
  128. foreach (Scene scene in row.Values)
  129. {
  130. action(scene);
  131. }
  132. }
  133. }
  134. /// <summary>
  135. /// Returns the scene at position 'location'.
  136. /// </summary>
  137. /// <param name="location">A location in the grid</param>
  138. /// <param name="scene">The scene at this location</param>
  139. /// <returns>Whether the scene was found</returns>
  140. public bool TryGetScene(Point location, out Scene scene)
  141. {
  142. SortedDictionary<uint, Scene> row;
  143. if (Regions.TryGetValue((uint)location.Y, out row))
  144. {
  145. if (row.TryGetValue((uint)location.X, out scene))
  146. return true;
  147. }
  148. scene = null;
  149. return false;
  150. }
  151. }
  152. }