aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMelanie Thielker2008-10-11 00:39:43 +0000
committerMelanie Thielker2008-10-11 00:39:43 +0000
commit2214b2f5783a4015f9fcfba6b2e7265c6bb01020 (patch)
treee284886cdef1f8d297955bc54b2faf31d96dd10c
parentEliminate some unnecessary polygons (diff)
downloadopensim-SC-2214b2f5783a4015f9fcfba6b2e7265c6bb01020.zip
opensim-SC-2214b2f5783a4015f9fcfba6b2e7265c6bb01020.tar.gz
opensim-SC-2214b2f5783a4015f9fcfba6b2e7265c6bb01020.tar.bz2
opensim-SC-2214b2f5783a4015f9fcfba6b2e7265c6bb01020.tar.xz
Commit Diva's new patch for the DataSnapshot. Comment the default
metaverseink search provider to prevent accidental data exposure.
-rw-r--r--OpenSim/Region/DataSnapshot/DataSnapshotManager.cs50
-rw-r--r--OpenSim/Region/DataSnapshot/LandSnapshot.cs248
-rw-r--r--bin/OpenSim.ini.example10
3 files changed, 164 insertions, 144 deletions
diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
index 586b665..6af6574 100644
--- a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
+++ b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
@@ -55,6 +55,7 @@ namespace OpenSim.Region.DataSnapshot
55 private List<String> m_disabledModules = new List<String>(); 55 private List<String> m_disabledModules = new List<String>();
56 private Dictionary<string, string> m_gridinfo = new Dictionary<string, string>(); 56 private Dictionary<string, string> m_gridinfo = new Dictionary<string, string>();
57 private string m_snapsDir = "DataSnapshot"; 57 private string m_snapsDir = "DataSnapshot";
58 private string m_exposure_level = "minimum";
58 59
59 //Lists of stuff we need 60 //Lists of stuff we need
60 private List<Scene> m_scenes = new List<Scene>(); 61 private List<Scene> m_scenes = new List<Scene>();
@@ -82,6 +83,15 @@ namespace OpenSim.Region.DataSnapshot
82 83
83 #endregion 84 #endregion
84 85
86 #region Properties
87
88 public string ExposureLevel
89 {
90 get { return m_exposure_level; }
91 }
92
93 #endregion
94
85 #region IRegionModule 95 #region IRegionModule
86 96
87 public void Close() {} 97 public void Close() {}
@@ -92,23 +102,24 @@ namespace OpenSim.Region.DataSnapshot
92 m_configLoaded = true; 102 m_configLoaded = true;
93 m_log.Info("[DATASNAPSHOT]: Loading configuration"); 103 m_log.Info("[DATASNAPSHOT]: Loading configuration");
94 //Read from the config for options 104 //Read from the config for options
95 lock (m_syncInit) 105 lock (m_syncInit)
96 { 106 {
97 try 107 try
98 { 108 {
99 m_enabled = config.Configs["DataSnapshot"].GetBoolean("index_sims", m_enabled); 109 m_enabled = config.Configs["DataSnapshot"].GetBoolean("index_sims", m_enabled);
100 if (config.Configs["Startup"].GetBoolean("gridmode", true)) 110 if (config.Configs["Startup"].GetBoolean("gridmode", true))
101 { 111 {
102 m_gridinfo.Add("gridserverURL", config.Configs["Network"].GetString("grid_server_url", "harbl")); 112 m_gridinfo.Add("gridserverURL", config.Configs["Network"].GetString("grid_server_url", "harbl"));
103 m_gridinfo.Add("userserverURL", config.Configs["Network"].GetString("user_server_url", "harbl")); 113 m_gridinfo.Add("userserverURL", config.Configs["Network"].GetString("user_server_url", "harbl"));
104 m_gridinfo.Add("assetserverURL", config.Configs["Network"].GetString("asset_server_url", "harbl")); 114 m_gridinfo.Add("assetserverURL", config.Configs["Network"].GetString("asset_server_url", "harbl"));
105 } 115 }
106 else 116 else
107 { 117 {
108 //Non gridmode stuff 118 //Non gridmode stuff
109 } 119 }
110 120
111 m_gridinfo.Add("Name", config.Configs["DataSnapshot"].GetString("gridname", "harbl")); 121 m_gridinfo.Add("Name", config.Configs["DataSnapshot"].GetString("gridname", "harbl"));
122 m_exposure_level = config.Configs["DataSnapshot"].GetString("data_exposure", m_exposure_level);
112 m_period = config.Configs["DataSnapshot"].GetInt("default_snapshot_period", m_period); 123 m_period = config.Configs["DataSnapshot"].GetInt("default_snapshot_period", m_period);
113 m_maxStales = config.Configs["DataSnapshot"].GetInt("max_changes_before_update", m_maxStales); 124 m_maxStales = config.Configs["DataSnapshot"].GetInt("max_changes_before_update", m_maxStales);
114 m_snapsDir = config.Configs["DataSnapshot"].GetString("snapshot_cache_directory", m_snapsDir); 125 m_snapsDir = config.Configs["DataSnapshot"].GetString("snapshot_cache_directory", m_snapsDir);
@@ -116,10 +127,13 @@ namespace OpenSim.Region.DataSnapshot
116 m_listener_port = config.Configs["Network"].GetString("http_listener_port", m_listener_port); 127 m_listener_port = config.Configs["Network"].GetString("http_listener_port", m_listener_port);
117 128
118 String[] annoying_string_array = config.Configs["DataSnapshot"].GetString("disable_modules", "").Split(".".ToCharArray()); 129 String[] annoying_string_array = config.Configs["DataSnapshot"].GetString("disable_modules", "").Split(".".ToCharArray());
119 foreach (String bloody_wanker in annoying_string_array) { 130 foreach (String bloody_wanker in annoying_string_array)
131 {
120 m_disabledModules.Add(bloody_wanker); 132 m_disabledModules.Add(bloody_wanker);
121 } 133 }
122 } catch (Exception) { 134 }
135 catch (Exception)
136 {
123 m_log.Info("[DATASNAPSHOT]: Could not load configuration. DataSnapshot will be disabled."); 137 m_log.Info("[DATASNAPSHOT]: Could not load configuration. DataSnapshot will be disabled.");
124 m_enabled = false; 138 m_enabled = false;
125 return; 139 return;
@@ -147,7 +161,7 @@ namespace OpenSim.Region.DataSnapshot
147 161
148 MakeEverythingStale(); 162 MakeEverythingStale();
149 163
150 if (m_dataServices != "noservices") 164 if (m_dataServices != "" && m_dataServices != "noservices")
151 NotifyDataServices(m_dataServices); 165 NotifyDataServices(m_dataServices);
152 } 166 }
153 } 167 }
diff --git a/OpenSim/Region/DataSnapshot/LandSnapshot.cs b/OpenSim/Region/DataSnapshot/LandSnapshot.cs
index 562cd8a..e6b8e82 100644
--- a/OpenSim/Region/DataSnapshot/LandSnapshot.cs
+++ b/OpenSim/Region/DataSnapshot/LandSnapshot.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.DataSnapshot.Providers
44 public class LandSnapshot : IDataSnapshotProvider 44 public class LandSnapshot : IDataSnapshotProvider
45 { 45 {
46 private Scene m_scene = null; 46 private Scene m_scene = null;
47 // private DataSnapshotManager m_parent = null; 47 private DataSnapshotManager m_parent = null;
48 //private Dictionary<int, Land> m_landIndexed = new Dictionary<int, Land>(); 48 //private Dictionary<int, Land> m_landIndexed = new Dictionary<int, Land>();
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 private bool m_stale = true; 50 private bool m_stale = true;
@@ -107,7 +107,7 @@ namespace OpenSim.Region.DataSnapshot.Providers
107 public void Initialize(Scene scene, DataSnapshotManager parent) 107 public void Initialize(Scene scene, DataSnapshotManager parent)
108 { 108 {
109 m_scene = scene; 109 m_scene = scene;
110 // m_parent = parent; 110 m_parent = parent;
111 111
112 //Brought back from the dead for staleness checks. 112 //Brought back from the dead for staleness checks.
113 m_scene.EventManager.OnNewClient += OnNewClient; 113 m_scene.EventManager.OnNewClient += OnNewClient;
@@ -137,135 +137,137 @@ namespace OpenSim.Region.DataSnapshot.Providers
137 LandObject land = (LandObject)parcel_interface; 137 LandObject land = (LandObject)parcel_interface;
138 138
139 LandData parcel = land.landData; 139 LandData parcel = land.landData;
140 // if ((parcel.Flags & (uint)Parcel.ParcelFlags.ShowDirectory) == (uint)Parcel.ParcelFlags.ShowDirectory) 140 if (m_parent.ExposureLevel.Equals("all") ||
141 // { 141 (m_parent.ExposureLevel.Equals("minimum") &&
142 142 (parcel.Flags & (uint)Parcel.ParcelFlags.ShowDirectory) == (uint)Parcel.ParcelFlags.ShowDirectory))
143 //TODO: make better method of marshalling data from LandData to XmlNode
144 XmlNode xmlparcel = nodeFactory.CreateNode(XmlNodeType.Element, "parcel", "");
145
146 // Attributes of the parcel node
147 XmlAttribute scripts_attr = nodeFactory.CreateAttribute("scripts");
148 scripts_attr.Value = GetScriptsPermissions(parcel);
149 XmlAttribute build_attr = nodeFactory.CreateAttribute("build");
150 build_attr.Value = GetBuildPermissions(parcel);
151 XmlAttribute public_attr = nodeFactory.CreateAttribute("public");
152 public_attr.Value = GetPublicPermissions(parcel);
153 // Check the category of the Parcel
154 XmlAttribute category_attr = nodeFactory.CreateAttribute("category");
155 category_attr.Value = ((int)parcel.Category).ToString();
156 // Check if the parcel is for sale
157 XmlAttribute forsale_attr = nodeFactory.CreateAttribute("forsale");
158 forsale_attr.Value = CheckForSale(parcel);
159 XmlAttribute sales_attr = nodeFactory.CreateAttribute("salesprice");
160 sales_attr.Value = parcel.SalePrice.ToString();
161
162 XmlAttribute directory_attr = nodeFactory.CreateAttribute("show_directory");
163 directory_attr.Value = GetShowInSearch(parcel);
164 //XmlAttribute entities_attr = nodeFactory.CreateAttribute("entities");
165 //entities_attr.Value = land.primsOverMe.Count.ToString();
166 xmlparcel.Attributes.Append(directory_attr);
167 xmlparcel.Attributes.Append(scripts_attr);
168 xmlparcel.Attributes.Append(build_attr);
169 xmlparcel.Attributes.Append(public_attr);
170 xmlparcel.Attributes.Append(category_attr);
171 xmlparcel.Attributes.Append(forsale_attr);
172 xmlparcel.Attributes.Append(sales_attr);
173 //xmlparcel.Attributes.Append(entities_attr);
174
175
176 //name, description, area, and UUID
177 XmlNode name = nodeFactory.CreateNode(XmlNodeType.Element, "name", "");
178 name.InnerText = parcel.Name;
179 xmlparcel.AppendChild(name);
180
181 XmlNode desc = nodeFactory.CreateNode(XmlNodeType.Element, "description", "");
182 desc.InnerText = parcel.Description;
183 xmlparcel.AppendChild(desc);
184
185 XmlNode uuid = nodeFactory.CreateNode(XmlNodeType.Element, "uuid", "");
186 uuid.InnerText = parcel.GlobalID.ToString();
187 xmlparcel.AppendChild(uuid);
188
189 XmlNode area = nodeFactory.CreateNode(XmlNodeType.Element, "area", "");
190 area.InnerText = parcel.Area.ToString();
191 xmlparcel.AppendChild(area);
192
193 //default location
194 XmlNode tpLocation = nodeFactory.CreateNode(XmlNodeType.Element, "location", "");
195 Vector3 loc = parcel.UserLocation;
196 if (loc.Equals(Vector3.Zero)) // This test is moot at this point: the location is wrong by default
197 loc = new Vector3((parcel.AABBMax.X + parcel.AABBMin.X) / 2, (parcel.AABBMax.Y + parcel.AABBMin.Y) / 2, (parcel.AABBMax.Z + parcel.AABBMin.Z) / 2);
198 tpLocation.InnerText = loc.X.ToString() + "/" + loc.Y.ToString() + "/" + loc.Z.ToString();
199 xmlparcel.AppendChild(tpLocation);
200
201 XmlNode infouuid = nodeFactory.CreateNode(XmlNodeType.Element, "infouuid", "");
202 uint x = (uint)loc.X, y = (uint)loc.Y;
203 findPointInParcel(land, ref x, ref y); // find a suitable spot
204 infouuid.InnerText = Util.BuildFakeParcelID(
205 m_scene.RegionInfo.RegionHandle, x, y).ToString();
206 xmlparcel.AppendChild(infouuid);
207
208 XmlNode dwell = nodeFactory.CreateNode(XmlNodeType.Element, "dwell", "");
209 dwell.InnerText = "0";
210 xmlparcel.AppendChild(dwell);
211
212 //TODO: figure how to figure out teleport system landData.landingType
213
214 //land texture snapshot uuid
215 if (parcel.SnapshotID != UUID.Zero)
216 { 143 {
217 XmlNode textureuuid = nodeFactory.CreateNode(XmlNodeType.Element, "image", "");
218 textureuuid.InnerText = parcel.SnapshotID.ToString();
219 xmlparcel.AppendChild(textureuuid);
220 }
221
222 //attached user and group
223 if (parcel.GroupID != UUID.Zero)
224 {
225 XmlNode groupblock = nodeFactory.CreateNode(XmlNodeType.Element, "group", "");
226 XmlNode groupuuid = nodeFactory.CreateNode(XmlNodeType.Element, "uuid", "");
227 groupuuid.InnerText = parcel.GroupID.ToString();
228 groupblock.AppendChild(groupuuid);
229
230 //No name yet, there's no way to get a group name since they don't exist yet.
231 //TODO: When groups are supported, add the group handling code.
232 144
233 xmlparcel.AppendChild(groupblock); 145 //TODO: make better method of marshalling data from LandData to XmlNode
234 } 146 XmlNode xmlparcel = nodeFactory.CreateNode(XmlNodeType.Element, "parcel", "");
235 147
236 if (!parcel.IsGroupOwned) 148 // Attributes of the parcel node
237 { 149 XmlAttribute scripts_attr = nodeFactory.CreateAttribute("scripts");
238 XmlNode userblock = nodeFactory.CreateNode(XmlNodeType.Element, "owner", ""); 150 scripts_attr.Value = GetScriptsPermissions(parcel);
151 XmlAttribute build_attr = nodeFactory.CreateAttribute("build");
152 build_attr.Value = GetBuildPermissions(parcel);
153 XmlAttribute public_attr = nodeFactory.CreateAttribute("public");
154 public_attr.Value = GetPublicPermissions(parcel);
155 // Check the category of the Parcel
156 XmlAttribute category_attr = nodeFactory.CreateAttribute("category");
157 category_attr.Value = ((int)parcel.Category).ToString();
158 // Check if the parcel is for sale
159 XmlAttribute forsale_attr = nodeFactory.CreateAttribute("forsale");
160 forsale_attr.Value = CheckForSale(parcel);
161 XmlAttribute sales_attr = nodeFactory.CreateAttribute("salesprice");
162 sales_attr.Value = parcel.SalePrice.ToString();
163
164 XmlAttribute directory_attr = nodeFactory.CreateAttribute("showinsearch");
165 directory_attr.Value = GetShowInSearch(parcel);
166 //XmlAttribute entities_attr = nodeFactory.CreateAttribute("entities");
167 //entities_attr.Value = land.primsOverMe.Count.ToString();
168 xmlparcel.Attributes.Append(directory_attr);
169 xmlparcel.Attributes.Append(scripts_attr);
170 xmlparcel.Attributes.Append(build_attr);
171 xmlparcel.Attributes.Append(public_attr);
172 xmlparcel.Attributes.Append(category_attr);
173 xmlparcel.Attributes.Append(forsale_attr);
174 xmlparcel.Attributes.Append(sales_attr);
175 //xmlparcel.Attributes.Append(entities_attr);
176
177
178 //name, description, area, and UUID
179 XmlNode name = nodeFactory.CreateNode(XmlNodeType.Element, "name", "");
180 name.InnerText = parcel.Name;
181 xmlparcel.AppendChild(name);
182
183 XmlNode desc = nodeFactory.CreateNode(XmlNodeType.Element, "description", "");
184 desc.InnerText = parcel.Description;
185 xmlparcel.AppendChild(desc);
186
187 XmlNode uuid = nodeFactory.CreateNode(XmlNodeType.Element, "uuid", "");
188 uuid.InnerText = parcel.GlobalID.ToString();
189 xmlparcel.AppendChild(uuid);
190
191 XmlNode area = nodeFactory.CreateNode(XmlNodeType.Element, "area", "");
192 area.InnerText = parcel.Area.ToString();
193 xmlparcel.AppendChild(area);
194
195 //default location
196 XmlNode tpLocation = nodeFactory.CreateNode(XmlNodeType.Element, "location", "");
197 Vector3 loc = parcel.UserLocation;
198 if (loc.Equals(Vector3.Zero)) // This test is moot at this point: the location is wrong by default
199 loc = new Vector3((parcel.AABBMax.X + parcel.AABBMin.X) / 2, (parcel.AABBMax.Y + parcel.AABBMin.Y) / 2, (parcel.AABBMax.Z + parcel.AABBMin.Z) / 2);
200 tpLocation.InnerText = loc.X.ToString() + "/" + loc.Y.ToString() + "/" + loc.Z.ToString();
201 xmlparcel.AppendChild(tpLocation);
202
203 XmlNode infouuid = nodeFactory.CreateNode(XmlNodeType.Element, "infouuid", "");
204 uint x = (uint)loc.X, y = (uint)loc.Y;
205 findPointInParcel(land, ref x, ref y); // find a suitable spot
206 infouuid.InnerText = Util.BuildFakeParcelID(
207 m_scene.RegionInfo.RegionHandle, x, y).ToString();
208 xmlparcel.AppendChild(infouuid);
209
210 XmlNode dwell = nodeFactory.CreateNode(XmlNodeType.Element, "dwell", "");
211 dwell.InnerText = "0";
212 xmlparcel.AppendChild(dwell);
213
214 //TODO: figure how to figure out teleport system landData.landingType
215
216 //land texture snapshot uuid
217 if (parcel.SnapshotID != UUID.Zero)
218 {
219 XmlNode textureuuid = nodeFactory.CreateNode(XmlNodeType.Element, "image", "");
220 textureuuid.InnerText = parcel.SnapshotID.ToString();
221 xmlparcel.AppendChild(textureuuid);
222 }
239 223
240 UUID userOwnerUUID = parcel.OwnerID; 224 //attached user and group
225 if (parcel.GroupID != UUID.Zero)
226 {
227 XmlNode groupblock = nodeFactory.CreateNode(XmlNodeType.Element, "group", "");
228 XmlNode groupuuid = nodeFactory.CreateNode(XmlNodeType.Element, "uuid", "");
229 groupuuid.InnerText = parcel.GroupID.ToString();
230 groupblock.AppendChild(groupuuid);
241 231
242 XmlNode useruuid = nodeFactory.CreateNode(XmlNodeType.Element, "uuid", ""); 232 //No name yet, there's no way to get a group name since they don't exist yet.
243 useruuid.InnerText = userOwnerUUID.ToString(); 233 //TODO: When groups are supported, add the group handling code.
244 userblock.AppendChild(useruuid);
245 234
246 try 235 xmlparcel.AppendChild(groupblock);
247 {
248 XmlNode username = nodeFactory.CreateNode(XmlNodeType.Element, "name", "");
249 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(userOwnerUUID);
250 username.InnerText = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName;
251 userblock.AppendChild(username);
252 } 236 }
253 catch (Exception) 237
238 if (!parcel.IsGroupOwned)
254 { 239 {
255 //m_log.Info("[DATASNAPSHOT]: Cannot find owner name; ignoring this parcel"); 240 XmlNode userblock = nodeFactory.CreateNode(XmlNodeType.Element, "owner", "");
241
242 UUID userOwnerUUID = parcel.OwnerID;
243
244 XmlNode useruuid = nodeFactory.CreateNode(XmlNodeType.Element, "uuid", "");
245 useruuid.InnerText = userOwnerUUID.ToString();
246 userblock.AppendChild(useruuid);
247
248 try
249 {
250 XmlNode username = nodeFactory.CreateNode(XmlNodeType.Element, "name", "");
251 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(userOwnerUUID);
252 username.InnerText = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName;
253 userblock.AppendChild(username);
254 }
255 catch (Exception)
256 {
257 //m_log.Info("[DATASNAPSHOT]: Cannot find owner name; ignoring this parcel");
258 }
259
260 xmlparcel.AppendChild(userblock);
256 } 261 }
257 262 //else
258 xmlparcel.AppendChild(userblock); 263 //{
264 // XmlAttribute type = (XmlAttribute)nodeFactory.CreateNode(XmlNodeType.Attribute, "type", "");
265 // type.InnerText = "owner";
266 // groupblock.Attributes.Append(type);
267 //}
268
269 parent.AppendChild(xmlparcel);
259 } 270 }
260 //else
261 //{
262 // XmlAttribute type = (XmlAttribute)nodeFactory.CreateNode(XmlNodeType.Attribute, "type", "");
263 // type.InnerText = "owner";
264 // groupblock.Attributes.Append(type);
265 //}
266
267 parent.AppendChild(xmlparcel);
268 // }
269 } 271 }
270 //snap.AppendChild(parent); 272 //snap.AppendChild(parent);
271 } 273 }
@@ -378,7 +380,7 @@ namespace OpenSim.Region.DataSnapshot.Providers
378 // another, smaller rectangular parcel). Both will have the same initial coordinates. 380 // another, smaller rectangular parcel). Both will have the same initial coordinates.
379 private void findPointInParcel(ILandObject land, ref uint refX, ref uint refY) 381 private void findPointInParcel(ILandObject land, ref uint refX, ref uint refY)
380 { 382 {
381 m_log.DebugFormat("[LAND] trying {0}, {1}", refX, refY); 383 m_log.DebugFormat("[DATASNAPSHOT] trying {0}, {1}", refX, refY);
382 // the point we started with already is in the parcel 384 // the point we started with already is in the parcel
383 if (land.containsPoint((int)refX, (int)refY)) return; 385 if (land.containsPoint((int)refX, (int)refY)) return;
384 386
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index c21e843..6a56853 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -569,6 +569,10 @@ max_listens_per_script = 64
569; Set index_sims to true to enable search engines to index your searchable data 569; Set index_sims to true to enable search engines to index your searchable data
570; If false, no data will be exposed, DataSnapshot module will be off, and you can ignore the rest of these search-related configs 570; If false, no data will be exposed, DataSnapshot module will be off, and you can ignore the rest of these search-related configs
571index_sims = false 571index_sims = false
572; The variable data_exposure controls what the regions expose:
573; minimum: exposes only things explicitly marked for search
574; all: exposes everything
575data_exposure = minimum
572; If search is on, change this to your grid name; will be ignored for standalones 576; If search is on, change this to your grid name; will be ignored for standalones
573gridname = "OSGrid" 577gridname = "OSGrid"
574; Period between data snapshots, in seconds. 20 minutes, for starters, so that you see the initial changes fast. 578; Period between data snapshots, in seconds. 20 minutes, for starters, so that you see the initial changes fast.
@@ -576,9 +580,9 @@ gridname = "OSGrid"
576default_snapshot_period = 1200 580default_snapshot_period = 1200
577; This will be created in bin, if it doesn't exist already. It will hold the data snapshots. 581; This will be created in bin, if it doesn't exist already. It will hold the data snapshots.
578snapshot_cache_directory = "DataSnapshot" 582snapshot_cache_directory = "DataSnapshot"
579; This semicolon-separated string serves to notify specific data services 583; This semicolon-separated string serves to notify specific data services about the existence
580; about the existence of this sim. 584; of this sim. Uncomment if you want to index your data with this and/or other search providers.
581data_services="http://metaverseink.com/cgi-bin/register.py" 585;data_services="http://metaverseink.com/cgi-bin/register.py"
582 586
583 587
584[Economy] 588[Economy]