aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorUbitUmarov2017-07-15 04:06:34 +0100
committerUbitUmarov2017-07-15 04:07:03 +0100
commit4b7f79e2967e8e7ac7c70118b70a9b66cd16a2b1 (patch)
treed4361a53efa6d2aac32ace697de1f6c7099d605f
parentadd Util.GetTimeStamp() that returns the stamp in seconds; use it on ubOde; s... (diff)
downloadopensim-SC_OLD-4b7f79e2967e8e7ac7c70118b70a9b66cd16a2b1.zip
opensim-SC_OLD-4b7f79e2967e8e7ac7c70118b70a9b66cd16a2b1.tar.gz
opensim-SC_OLD-4b7f79e2967e8e7ac7c70118b70a9b66cd16a2b1.tar.bz2
opensim-SC_OLD-4b7f79e2967e8e7ac7c70118b70a9b66cd16a2b1.tar.xz
fixes and changes on TreePopulatorModule. Please read OpenSimDefaults.ini
[Trees] section. Does need more work, and some hardcode settings may not be the optimal still"
-rw-r--r--OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs685
-rw-r--r--bin/OpenSimDefaults.ini20
2 files changed, 426 insertions, 279 deletions
diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
index da8c9a3..bdd875a 100644
--- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
+++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
@@ -27,8 +27,13 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO;
30using System.Reflection; 31using System.Reflection;
31using System.Timers; 32using System.Timers;
33using System.Threading;
34using System.Xml;
35using System.Xml.Serialization;
36
32using OpenMetaverse; 37using OpenMetaverse;
33using log4net; 38using log4net;
34using Mono.Addins; 39using Mono.Addins;
@@ -38,9 +43,7 @@ using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
38using OpenSim.Region.Framework.Interfaces; 43using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
40 45
41using System.Xml; 46using Timer= System.Timers.Timer;
42using System.Xml.Serialization;
43using System.IO;
44 47
45namespace OpenSim.Region.OptionalModules.World.TreePopulator 48namespace OpenSim.Region.OptionalModules.World.TreePopulator
46{ 49{
@@ -48,7 +51,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
48 /// Version 2.02 - Still hacky 51 /// Version 2.02 - Still hacky
49 /// </summary> 52 /// </summary>
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TreePopulatorModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TreePopulatorModule")]
51 public class TreePopulatorModule : INonSharedRegionModule, ICommandableModule, IVegetationModule 54 public class TreePopulatorModule : INonSharedRegionModule, ICommandableModule
52 { 55 {
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 private readonly Commander m_commander = new Commander("tree"); 57 private readonly Commander m_commander = new Commander("tree");
@@ -82,20 +85,20 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
82 { 85 {
83 Copse cp = (Copse)DeserializeObject(fileName); 86 Copse cp = (Copse)DeserializeObject(fileName);
84 87
85 this.m_name = cp.m_name; 88 m_name = cp.m_name;
86 this.m_frozen = cp.m_frozen; 89 m_frozen = cp.m_frozen;
87 this.m_tree_quantity = cp.m_tree_quantity; 90 m_tree_quantity = cp.m_tree_quantity;
88 this.m_treeline_high = cp.m_treeline_high; 91 m_treeline_high = cp.m_treeline_high;
89 this.m_treeline_low = cp.m_treeline_low; 92 m_treeline_low = cp.m_treeline_low;
90 this.m_range = cp.m_range; 93 m_range = cp.m_range;
91 this.m_tree_type = cp.m_tree_type; 94 m_tree_type = cp.m_tree_type;
92 this.m_seed_point = cp.m_seed_point; 95 m_seed_point = cp.m_seed_point;
93 this.m_initial_scale = cp.m_initial_scale; 96 m_initial_scale = cp.m_initial_scale;
94 this.m_maximum_scale = cp.m_maximum_scale; 97 m_maximum_scale = cp.m_maximum_scale;
95 this.m_initial_scale = cp.m_initial_scale; 98 m_initial_scale = cp.m_initial_scale;
96 this.m_rate = cp.m_rate; 99 m_rate = cp.m_rate;
97 this.m_planted = planted; 100 m_planted = planted;
98 this.m_trees = new List<UUID>(); 101 m_trees = new List<UUID>();
99 } 102 }
100 103
101 public Copse(string copsedef) 104 public Copse(string copsedef)
@@ -103,61 +106,63 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
103 char[] delimiterChars = {':', ';'}; 106 char[] delimiterChars = {':', ';'};
104 string[] field = copsedef.Split(delimiterChars); 107 string[] field = copsedef.Split(delimiterChars);
105 108
106 this.m_name = field[1].Trim(); 109 m_name = field[1].Trim();
107 this.m_frozen = (copsedef[0] == 'F'); 110 m_frozen = (copsedef[0] == 'F');
108 this.m_tree_quantity = int.Parse(field[2]); 111 m_tree_quantity = int.Parse(field[2]);
109 this.m_treeline_high = float.Parse(field[3], Culture.NumberFormatInfo); 112 m_treeline_high = float.Parse(field[3], Culture.NumberFormatInfo);
110 this.m_treeline_low = float.Parse(field[4], Culture.NumberFormatInfo); 113 m_treeline_low = float.Parse(field[4], Culture.NumberFormatInfo);
111 this.m_range = double.Parse(field[5], Culture.NumberFormatInfo); 114 m_range = double.Parse(field[5], Culture.NumberFormatInfo);
112 this.m_tree_type = (Tree) Enum.Parse(typeof(Tree),field[6]); 115 m_tree_type = (Tree) Enum.Parse(typeof(Tree),field[6]);
113 this.m_seed_point = Vector3.Parse(field[7]); 116 m_seed_point = Vector3.Parse(field[7]);
114 this.m_initial_scale = Vector3.Parse(field[8]); 117 m_initial_scale = Vector3.Parse(field[8]);
115 this.m_maximum_scale = Vector3.Parse(field[9]); 118 m_maximum_scale = Vector3.Parse(field[9]);
116 this.m_rate = Vector3.Parse(field[10]); 119 m_rate = Vector3.Parse(field[10]);
117 this.m_planted = true; 120 m_planted = true;
118 this.m_trees = new List<UUID>(); 121 m_trees = new List<UUID>();
119 } 122 }
120 123
121 public Copse(string name, int quantity, float high, float low, double range, Vector3 point, Tree type, Vector3 scale, Vector3 max_scale, Vector3 rate, List<UUID> trees) 124 public Copse(string name, int quantity, float high, float low, double range, Vector3 point, Tree type, Vector3 scale, Vector3 max_scale, Vector3 rate, List<UUID> trees)
122 { 125 {
123 this.m_name = name; 126 m_name = name;
124 this.m_frozen = false; 127 m_frozen = false;
125 this.m_tree_quantity = quantity; 128 m_tree_quantity = quantity;
126 this.m_treeline_high = high; 129 m_treeline_high = high;
127 this.m_treeline_low = low; 130 m_treeline_low = low;
128 this.m_range = range; 131 m_range = range;
129 this.m_tree_type = type; 132 m_tree_type = type;
130 this.m_seed_point = point; 133 m_seed_point = point;
131 this.m_initial_scale = scale; 134 m_initial_scale = scale;
132 this.m_maximum_scale = max_scale; 135 m_maximum_scale = max_scale;
133 this.m_rate = rate; 136 m_rate = rate;
134 this.m_planted = false; 137 m_planted = false;
135 this.m_trees = trees; 138 m_trees = trees;
136 } 139 }
137 140
138 public override string ToString() 141 public override string ToString()
139 { 142 {
140 string frozen = (this.m_frozen ? "F" : "A"); 143 string frozen = (m_frozen ? "F" : "A");
141 144
142 return string.Format("{0}TPM: {1}; {2}; {3:0.0}; {4:0.0}; {5:0.0}; {6}; {7:0.0}; {8:0.0}; {9:0.0}; {10:0.00};", 145 return string.Format("{0}TPM: {1}; {2}; {3:0.0}; {4:0.0}; {5:0.0}; {6}; {7:0.0}; {8:0.0}; {9:0.0}; {10:0.00};",
143 frozen, 146 frozen,
144 this.m_name, 147 m_name,
145 this.m_tree_quantity, 148 m_tree_quantity,
146 this.m_treeline_high, 149 m_treeline_high,
147 this.m_treeline_low, 150 m_treeline_low,
148 this.m_range, 151 m_range,
149 this.m_tree_type, 152 m_tree_type,
150 this.m_seed_point.ToString(), 153 m_seed_point.ToString(),
151 this.m_initial_scale.ToString(), 154 m_initial_scale.ToString(),
152 this.m_maximum_scale.ToString(), 155 m_maximum_scale.ToString(),
153 this.m_rate.ToString()); 156 m_rate.ToString());
154 } 157 }
155 } 158 }
156 159
157 private List<Copse> m_copse; 160 private List<Copse> m_copses = new List<Copse>();
158 161 private object mylock;
159 private double m_update_ms = 1000.0; // msec between updates 162 private double m_update_ms = 1000.0; // msec between updates
160 private bool m_active_trees = false; 163 private bool m_active_trees = false;
164 private bool m_enabled = true; // original default
165 private bool m_allowGrow = true; // original default
161 166
162 Timer CalculateTrees; 167 Timer CalculateTrees;
163 168
@@ -174,51 +179,51 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
174 179
175 public void Initialise(IConfigSource config) 180 public void Initialise(IConfigSource config)
176 { 181 {
177 182 IConfig moduleConfig = config.Configs["Trees"];
178 // ini file settings 183 if (moduleConfig != null)
179 try
180 {
181 m_active_trees = config.Configs["Trees"].GetBoolean("active_trees", m_active_trees);
182 }
183 catch (Exception)
184 { 184 {
185 m_log.Debug("[TREES]: ini failure for active_trees - using default"); 185 m_enabled = moduleConfig.GetBoolean("enabled", m_enabled);
186 m_active_trees = moduleConfig.GetBoolean("active_trees", m_active_trees);
187 m_allowGrow = moduleConfig.GetBoolean("allowGrow", m_allowGrow);
188 m_update_ms = moduleConfig.GetDouble("update_rate", m_update_ms);
186 } 189 }
187 190
188 try 191 if(!m_enabled)
189 { 192 return;
190 m_update_ms = config.Configs["Trees"].GetDouble("update_rate", m_update_ms); 193
191 } 194 m_copses = new List<Copse>();
192 catch (Exception) 195 mylock = new object();
193 {
194 m_log.Debug("[TREES]: ini failure for update_rate - using default");
195 }
196 196
197 InstallCommands(); 197 InstallCommands();
198 198
199 m_log.Debug("[TREES]: Initialised tree module"); 199 m_log.Debug("[TREES]: Initialised tree populator module");
200 } 200 }
201 201
202 public void AddRegion(Scene scene) 202 public void AddRegion(Scene scene)
203 { 203 {
204 if(!m_enabled)
205 return;
204 m_scene = scene; 206 m_scene = scene;
205 m_scene.RegisterModuleCommander(m_commander); 207 m_scene.RegisterModuleCommander(m_commander);
206 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; 208 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
207 209 m_scene.EventManager.OnPrimsLoaded += EventManager_OnPrimsLoaded;
208 } 210 }
209 211
210 public void RemoveRegion(Scene scene) 212 public void RemoveRegion(Scene scene)
211 { 213 {
212 } 214 if(!m_enabled)
215 return;
216 if(m_active_trees && CalculateTrees != null)
217 {
218 CalculateTrees.Dispose();
219 CalculateTrees = null;
220 }
221 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
222 m_scene.EventManager.OnPrimsLoaded -= EventManager_OnPrimsLoaded;
223 }
213 224
214 public void RegionLoaded(Scene scene) 225 public void RegionLoaded(Scene scene)
215 { 226 {
216 ReloadCopse();
217 if (m_copse.Count > 0)
218 m_log.Info("[TREES]: Copse load complete");
219
220 if (m_active_trees)
221 activeizeTreeze(true);
222 } 227 }
223 228
224 public void Close() 229 public void Close()
@@ -240,6 +245,16 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
240 245
241 //-------------------------------------------------------------- 246 //--------------------------------------------------------------
242 247
248 private void EventManager_OnPrimsLoaded(Scene s)
249 {
250 ReloadCopse();
251 if (m_copses.Count > 0)
252 m_log.Info("[TREES]: Copses loaded" );
253
254 if (m_active_trees)
255 activeizeTreeze(true);
256 }
257
243 #region ICommandableModule Members 258 #region ICommandableModule Members
244 259
245 private void HandleTreeActive(Object[] args) 260 private void HandleTreeActive(Object[] args)
@@ -267,22 +282,51 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
267 string copsename = ((string)args[0]).Trim(); 282 string copsename = ((string)args[0]).Trim();
268 Boolean freezeState = (Boolean) args[1]; 283 Boolean freezeState = (Boolean) args[1];
269 284
270 foreach (Copse cp in m_copse) 285 foreach (Copse cp in m_copses)
271 { 286 {
272 if (cp.m_name == copsename && (!cp.m_frozen && freezeState || cp.m_frozen && !freezeState)) 287 if (cp.m_name == copsename)
288 continue;
289
290 if(!cp.m_frozen && freezeState || cp.m_frozen && !freezeState)
273 { 291 {
274 cp.m_frozen = freezeState; 292 cp.m_frozen = freezeState;
293 List<UUID> losttrees = new List<UUID>();
275 foreach (UUID tree in cp.m_trees) 294 foreach (UUID tree in cp.m_trees)
276 { 295 {
277 SceneObjectPart sop = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; 296 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
278 sop.Name = (freezeState ? sop.Name.Replace("ATPM", "FTPM") : sop.Name.Replace("FTPM", "ATPM")); 297 if(sog != null && !sog.IsDeleted)
279 sop.ParentGroup.HasGroupChanged = true; 298 {
299 SceneObjectPart sop = sog.RootPart;
300 string name = sop.Name;
301 if(freezeState)
302 {
303 if(name.StartsWith("FTPM"))
304 continue;
305 if(!name.StartsWith("ATPM"))
306 continue;
307 sop.Name = sop.Name.Replace("ATPM", "FTPM");
308 }
309 else
310 {
311 if(name.StartsWith("ATPM"))
312 continue;
313 if(!name.StartsWith("FTPM"))
314 continue;
315 sop.Name = sop.Name.Replace("FTPM", "ATPM");
316 }
317 sop.ParentGroup.HasGroupChanged = true;
318 sog.ScheduleGroupForFullUpdate();
319 }
320 else
321 losttrees.Add(tree);
280 } 322 }
323 foreach (UUID tree in losttrees)
324 cp.m_trees.Remove(tree);
281 325
282 m_log.InfoFormat("[TREES]: Activity for copse {0} is frozen {1}", copsename, freezeState); 326 m_log.InfoFormat("[TREES]: Activity for copse {0} is frozen {1}", copsename, freezeState);
283 return; 327 return;
284 } 328 }
285 else if (cp.m_name == copsename && (cp.m_frozen && freezeState || !cp.m_frozen && !freezeState)) 329 else
286 { 330 {
287 m_log.InfoFormat("[TREES]: Copse {0} is already in the requested freeze state", copsename); 331 m_log.InfoFormat("[TREES]: Copse {0} is already in the requested freeze state", copsename);
288 return; 332 return;
@@ -297,17 +341,21 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
297 341
298 m_log.InfoFormat("[TREES]: Loading copse definition...."); 342 m_log.InfoFormat("[TREES]: Loading copse definition....");
299 343
300 copse = new Copse(((string)args[0]), false); 344 lock(mylock)
301 foreach (Copse cp in m_copse)
302 { 345 {
303 if (cp.m_name == copse.m_name) 346 copse = new Copse(((string)args[0]), false);
304 { 347 {
305 m_log.InfoFormat("[TREES]: Copse: {0} is already defined - command failed", copse.m_name); 348 foreach (Copse cp in m_copses)
306 return; 349 {
350 if (cp.m_name == copse.m_name)
351 {
352 m_log.InfoFormat("[TREES]: Copse: {0} is already defined - command failed", copse.m_name);
353 return;
354 }
355 }
307 } 356 }
357 m_copses.Add(copse);
308 } 358 }
309
310 m_copse.Add(copse);
311 m_log.InfoFormat("[TREES]: Loaded copse: {0}", copse.ToString()); 359 m_log.InfoFormat("[TREES]: Loaded copse: {0}", copse.ToString());
312 } 360 }
313 361
@@ -318,20 +366,23 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
318 m_log.InfoFormat("[TREES]: New tree planting for copse {0}", copsename); 366 m_log.InfoFormat("[TREES]: New tree planting for copse {0}", copsename);
319 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; 367 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
320 368
321 foreach (Copse copse in m_copse) 369 lock(mylock)
322 { 370 {
323 if (copse.m_name == copsename) 371 foreach (Copse copse in m_copses)
324 { 372 {
325 if (!copse.m_planted) 373 if (copse.m_name == copsename)
326 {
327 // The first tree for a copse is created here
328 CreateTree(uuid, copse, copse.m_seed_point);
329 copse.m_planted = true;
330 return;
331 }
332 else
333 { 374 {
334 m_log.InfoFormat("[TREES]: Copse {0} has already been planted", copsename); 375 if (!copse.m_planted)
376 {
377 // The first tree for a copse is created here
378 CreateTree(uuid, copse, copse.m_seed_point, true);
379 copse.m_planted = true;
380 return;
381 }
382 else
383 {
384 m_log.InfoFormat("[TREES]: Copse {0} has already been planted", copsename);
385 }
335 } 386 }
336 } 387 }
337 } 388 }
@@ -376,43 +427,46 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
376 string copsename = ((string)args[0]).Trim(); 427 string copsename = ((string)args[0]).Trim();
377 Copse copseIdentity = null; 428 Copse copseIdentity = null;
378 429
379 foreach (Copse cp in m_copse) 430 lock(mylock)
380 { 431 {
381 if (cp.m_name == copsename) 432 foreach (Copse cp in m_copses)
382 { 433 {
383 copseIdentity = cp; 434 if (cp.m_name == copsename)
435 {
436 copseIdentity = cp;
437 }
384 } 438 }
385 }
386 439
387 if (copseIdentity != null) 440 if (copseIdentity != null)
388 {
389 foreach (UUID tree in copseIdentity.m_trees)
390 { 441 {
391 if (m_scene.Entities.ContainsKey(tree)) 442 foreach (UUID tree in copseIdentity.m_trees)
392 {
393 SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
394 // Delete tree and alert clients (not silent)
395 m_scene.DeleteSceneObject(selectedTree.ParentGroup, false);
396 }
397 else
398 { 443 {
399 m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); 444 if (m_scene.Entities.ContainsKey(tree))
445 {
446 SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
447 // Delete tree and alert clients (not silent)
448 m_scene.DeleteSceneObject(selectedTree.ParentGroup, false);
449 }
450 else
451 {
452 m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
453 }
400 } 454 }
455 copseIdentity.m_trees = null;
456 m_copses.Remove(copseIdentity);
457 m_log.InfoFormat("[TREES]: Copse {0} has been removed", copsename);
458 }
459 else
460 {
461 m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename);
401 } 462 }
402 copseIdentity.m_trees = new List<UUID>();
403 m_copse.Remove(copseIdentity);
404 m_log.InfoFormat("[TREES]: Copse {0} has been removed", copsename);
405 }
406 else
407 {
408 m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename);
409 } 463 }
410 } 464 }
411 465
412 private void HandleTreeStatistics(Object[] args) 466 private void HandleTreeStatistics(Object[] args)
413 { 467 {
414 m_log.InfoFormat("[TREES]: Activity State: {0}; Update Rate: {1}", m_active_trees, m_update_ms); 468 m_log.InfoFormat("[TREES]: Activity State: {0}; Update Rate: {1}", m_active_trees, m_update_ms);
415 foreach (Copse cp in m_copse) 469 foreach (Copse cp in m_copses)
416 { 470 {
417 m_log.InfoFormat("[TREES]: Copse {0}; {1} trees; frozen {2}", cp.m_name, cp.m_trees.Count, cp.m_frozen); 471 m_log.InfoFormat("[TREES]: Copse {0}; {1} trees; frozen {2}", cp.m_name, cp.m_trees.Count, cp.m_frozen);
418 } 472 }
@@ -442,7 +496,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
442 treeRateCommand.AddArgument("updateRate", "The required update rate (minimum 1000.0)", "Double"); 496 treeRateCommand.AddArgument("updateRate", "The required update rate (minimum 1000.0)", "Double");
443 497
444 Command treeReloadCommand = 498 Command treeReloadCommand =
445 new Command("reload", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeReload, "Reload copse definitions from the in-scene trees"); 499 new Command("reload", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeReload, "Reload copses from the in-scene trees");
446 500
447 Command treeRemoveCommand = 501 Command treeRemoveCommand =
448 new Command("remove", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeRemove, "Remove a copse definition and all its in-scene trees"); 502 new Command("remove", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeRemove, "Remove a copse definition and all its in-scene trees");
@@ -499,34 +553,17 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
499 treeShape.Scale = scale; 553 treeShape.Scale = scale;
500 treeShape.State = (byte)treeType; 554 treeShape.State = (byte)treeType;
501 555
502 return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape); 556 SceneObjectGroup sog = new SceneObjectGroup(uuid, position, rotation, treeShape);
503 } 557 SceneObjectPart rootPart = sog.RootPart;
504
505 #endregion
506
507 #region IEntityCreator Members
508
509 protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.NewTree, PCode.Tree };
510 public PCode[] CreationCapabilities { get { return creationCapabilities; } }
511
512 public SceneObjectGroup CreateEntity(
513 UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
514 {
515 if (Array.IndexOf(creationCapabilities, (PCode)shape.PCode) < 0)
516 {
517 m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name);
518 return null;
519 }
520
521 SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape);
522 SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID);
523 558
524 rootPart.AddFlag(PrimFlags.Phantom); 559 rootPart.AddFlag(PrimFlags.Phantom);
525 560
526 sceneObject.SetGroup(groupID, null); 561 sog.SetGroup(groupID, null);
527 m_scene.AddNewSceneObject(sceneObject, true); 562 m_scene.AddNewSceneObject(sog, true, false);
528 sceneObject.InvalidateEffectivePerms(); 563 sog.IsSelected = false;
529 return sceneObject; 564 rootPart.IsSelected = false;
565 sog.InvalidateEffectivePerms();
566 return sog;
530 } 567 }
531 568
532 #endregion 569 #endregion
@@ -569,26 +606,27 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
569 606
570 private void ReloadCopse() 607 private void ReloadCopse()
571 { 608 {
572 m_copse = new List<Copse>(); 609 m_copses = new List<Copse>();
573 610
574 EntityBase[] objs = m_scene.GetEntities(); 611 List<SceneObjectGroup> grps = m_scene.GetSceneObjectGroups();
575 foreach (EntityBase obj in objs) 612 foreach (SceneObjectGroup grp in grps)
576 { 613 {
577 if (obj is SceneObjectGroup) 614 if(grp.RootPart.Shape.PCode != (byte)PCode.NewTree && grp.RootPart.Shape.PCode != (byte)PCode.Tree)
578 { 615 continue;
579 SceneObjectGroup grp = (SceneObjectGroup)obj;
580 616
581 if (grp.Name.Length > 5 && (grp.Name.Substring(0, 5) == "ATPM:" || grp.Name.Substring(0, 5) == "FTPM:")) 617 if (grp.Name.Length > 5 && (grp.Name.Substring(0, 5) == "ATPM:" || grp.Name.Substring(0, 5) == "FTPM:"))
618 {
619 // Create a new copse definition or add uuid to an existing definition
620 try
582 { 621 {
583 // Create a new copse definition or add uuid to an existing definition 622 Boolean copsefound = false;
584 try 623 Copse grpcopse = new Copse(grp.Name);
585 {
586 Boolean copsefound = false;
587 Copse copse = new Copse(grp.Name);
588 624
589 foreach (Copse cp in m_copse) 625 lock(mylock)
626 {
627 foreach (Copse cp in m_copses)
590 { 628 {
591 if (cp.m_name == copse.m_name) 629 if (cp.m_name == grpcopse.m_name)
592 { 630 {
593 copsefound = true; 631 copsefound = true;
594 cp.m_trees.Add(grp.UUID); 632 cp.m_trees.Add(grp.UUID);
@@ -598,15 +636,15 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
598 636
599 if (!copsefound) 637 if (!copsefound)
600 { 638 {
601 m_log.InfoFormat("[TREES]: Found copse {0}", grp.Name); 639 m_log.InfoFormat("[TREES]: adding copse {0}", grpcopse.m_name);
602 m_copse.Add(copse); 640 grpcopse.m_trees.Add(grp.UUID);
603 copse.m_trees.Add(grp.UUID); 641 m_copses.Add(grpcopse);
604 } 642 }
605 } 643 }
606 catch 644 }
607 { 645 catch
608 m_log.InfoFormat("[TREES]: Ill formed copse definition {0} - ignoring", grp.Name); 646 {
609 } 647 m_log.InfoFormat("[TREES]: Ill formed copse definition {0} - ignoring", grp.Name);
610 } 648 }
611 } 649 }
612 } 650 }
@@ -617,8 +655,10 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
617 { 655 {
618 if (activeYN) 656 if (activeYN)
619 { 657 {
620 CalculateTrees = new Timer(m_update_ms); 658 if(CalculateTrees == null)
659 CalculateTrees = new Timer(m_update_ms);
621 CalculateTrees.Elapsed += CalculateTrees_Elapsed; 660 CalculateTrees.Elapsed += CalculateTrees_Elapsed;
661 CalculateTrees.AutoReset = false;
622 CalculateTrees.Start(); 662 CalculateTrees.Start();
623 } 663 }
624 else 664 else
@@ -629,154 +669,253 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
629 669
630 private void growTrees() 670 private void growTrees()
631 { 671 {
632 foreach (Copse copse in m_copse) 672 if(!m_allowGrow)
673 return;
674
675 foreach (Copse copse in m_copses)
633 { 676 {
634 if (!copse.m_frozen) 677 if (copse.m_frozen)
678 continue;
679
680 if(copse.m_trees.Count == 0)
681 continue;
682
683 float maxscale = copse.m_maximum_scale.Z;
684 float ratescale = 1.0f;
685 List<UUID> losttrees = new List<UUID>();
686 foreach (UUID tree in copse.m_trees)
635 { 687 {
636 foreach (UUID tree in copse.m_trees) 688 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
637 {
638 if (m_scene.Entities.ContainsKey(tree))
639 {
640 SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
641 689
642 if (s_tree.Scale.X < copse.m_maximum_scale.X && s_tree.Scale.Y < copse.m_maximum_scale.Y && s_tree.Scale.Z < copse.m_maximum_scale.Z) 690 if (sog != null && !sog.IsDeleted)
643 { 691 {
644 s_tree.Scale += copse.m_rate; 692 SceneObjectPart s_tree = sog.RootPart;
645 s_tree.ParentGroup.HasGroupChanged = true; 693 if (s_tree.Scale.Z < maxscale)
646 s_tree.ScheduleFullUpdate();
647 }
648 }
649 else
650 { 694 {
651 m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); 695 ratescale = (float)Util.RandomClass.NextDouble();
696 if(ratescale < 0.2f)
697 ratescale = 0.2f;
698 s_tree.Scale += copse.m_rate * ratescale;
699 sog.HasGroupChanged = true;
700 s_tree.ScheduleFullUpdate();
652 } 701 }
653 } 702 }
703 else
704 losttrees.Add(tree);
654 } 705 }
706
707 foreach (UUID tree in losttrees)
708 copse.m_trees.Remove(tree);
655 } 709 }
656 } 710 }
657 711
658 private void seedTrees() 712 private void seedTrees()
659 { 713 {
660 foreach (Copse copse in m_copse) 714 foreach (Copse copse in m_copses)
661 { 715 {
662 if (!copse.m_frozen) 716 if (copse.m_frozen)
717 continue;
718
719 if(copse.m_trees.Count == 0)
720 return;
721
722 bool low = copse.m_trees.Count < (int)(copse.m_tree_quantity * 0.8f);
723
724 if (!low && Util.RandomClass.NextDouble() < 0.75)
725 return;
726
727 int maxbirths = (int)(copse.m_tree_quantity) - copse.m_trees.Count;
728 if(maxbirths <= 1)
729 return;
730
731 if(maxbirths > 20)
732 maxbirths = 20;
733
734 float minscale = 0;
735 if(!low && m_allowGrow)
736 minscale = copse.m_maximum_scale.Z * 0.75f;;
737
738 int i = 0;
739 UUID[] current = copse.m_trees.ToArray();
740 while(--maxbirths > 0)
663 { 741 {
664 foreach (UUID tree in copse.m_trees) 742 if(current.Length > 1)
743 i = Util.RandomClass.Next(current.Length -1);
744
745 UUID tree = current[i];
746 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
747
748 if (sog != null && !sog.IsDeleted)
665 { 749 {
666 if (m_scene.Entities.ContainsKey(tree)) 750 SceneObjectPart s_tree = sog.RootPart;
667 {
668 SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
669 751
670 if (copse.m_trees.Count < copse.m_tree_quantity) 752 // Tree has grown enough to seed if it has grown by at least 25% of seeded to full grown height
671 { 753 if (s_tree.Scale.Z > minscale)
672 // Tree has grown enough to seed if it has grown by at least 25% of seeded to full grown height 754 SpawnChild(copse, s_tree, true);
673 if (s_tree.Scale.Z > copse.m_initial_scale.Z + (copse.m_maximum_scale.Z - copse.m_initial_scale.Z) / 4.0)
674 {
675 if (Util.RandomClass.NextDouble() > 0.75)
676 {
677 SpawnChild(copse, s_tree);
678 }
679 }
680 }
681 }
682 else
683 {
684 m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
685 }
686 } 755 }
687 } 756 else if(copse.m_trees.Contains(tree))
757 copse.m_trees.Remove(tree);
758 }
688 } 759 }
689 } 760 }
690 761
691 private void killTrees() 762 private void killTrees()
692 { 763 {
693 foreach (Copse copse in m_copse) 764 foreach (Copse copse in m_copses)
694 { 765 {
695 if (!copse.m_frozen && copse.m_trees.Count >= copse.m_tree_quantity) 766 if (copse.m_frozen)
696 { 767 continue;
697 foreach (UUID tree in copse.m_trees)
698 {
699 double killLikelyhood = 0.0;
700 768
701 if (m_scene.Entities.ContainsKey(tree)) 769 if (Util.RandomClass.NextDouble() < 0.25)
702 { 770 return;
703 SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
704 double selectedTreeScale = Math.Sqrt(Math.Pow(selectedTree.Scale.X, 2) +
705 Math.Pow(selectedTree.Scale.Y, 2) +
706 Math.Pow(selectedTree.Scale.Z, 2));
707
708 foreach (UUID picktree in copse.m_trees)
709 {
710 if (picktree != tree)
711 {
712 SceneObjectPart pickedTree = ((SceneObjectGroup)m_scene.Entities[picktree]).RootPart;
713
714 double pickedTreeScale = Math.Sqrt(Math.Pow(pickedTree.Scale.X, 2) +
715 Math.Pow(pickedTree.Scale.Y, 2) +
716 Math.Pow(pickedTree.Scale.Z, 2));
717 771
718 double pickedTreeDistance = Vector3.Distance(pickedTree.AbsolutePosition, selectedTree.AbsolutePosition); 772 int maxbdeaths = copse.m_trees.Count - (int)(copse.m_tree_quantity * .98f) ;
773 if(maxbdeaths < 1)
774 return;
719 775
720 killLikelyhood += (selectedTreeScale / (pickedTreeScale * pickedTreeDistance)) * 0.1; 776 float odds;
721 } 777 float scale = 1.0f / copse.m_maximum_scale.Z;
722 }
723 778
724 if (Util.RandomClass.NextDouble() < killLikelyhood) 779 int ntries = maxbdeaths * 4;
725 { 780 while(ntries-- > 0 )
726 // Delete tree and alert clients (not silent) 781 {
727 m_scene.DeleteSceneObject(selectedTree.ParentGroup, false); 782 int next = 0;
728 copse.m_trees.Remove(selectedTree.ParentGroup.UUID); 783 if (copse.m_trees.Count > 1)
729 break; 784 next = Util.RandomClass.Next(copse.m_trees.Count - 1);
730 } 785 UUID tree = copse.m_trees[next];
786 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
787 if (sog != null && !sog.IsDeleted)
788 {
789 if(m_allowGrow)
790 {
791 odds = sog.RootPart.Scale.Z * scale;
792 odds = odds * odds * odds;
793 odds *= (float)Util.RandomClass.NextDouble();
731 } 794 }
732 else 795 else
733 { 796 {
734 m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); 797 odds = (float)Util.RandomClass.NextDouble();
798 odds = odds * odds * odds;
735 } 799 }
800
801 if(odds > 0.9f)
802 {
803 m_scene.DeleteSceneObject(sog, false);
804 if(maxbdeaths <= 0)
805 break;
806 }
807 }
808 else
809 {
810 copse.m_trees.Remove(tree);
811 if(copse.m_trees.Count - (int)(copse.m_tree_quantity * .98f) <= 0 )
812 break;
736 } 813 }
737 } 814 }
738 } 815 }
739 } 816 }
740 817
741 private void SpawnChild(Copse copse, SceneObjectPart s_tree) 818 private void SpawnChild(Copse copse, SceneObjectPart s_tree, bool low)
742 { 819 {
743 Vector3 position = new Vector3(); 820 Vector3 position = new Vector3();
744 821
745 double randX = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); 822 float randX = copse.m_maximum_scale.X * 1.25f;
746 double randY = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); 823 float randY = copse.m_maximum_scale.Y * 1.25f;
747 824
825 float r = (float)Util.RandomClass.NextDouble();
826 randX *= 2.0f * r - 1.0f;
748 position.X = s_tree.AbsolutePosition.X + (float)randX; 827 position.X = s_tree.AbsolutePosition.X + (float)randX;
828
829 r = (float)Util.RandomClass.NextDouble();
830 randY *= 2.0f * r - 1.0f;
749 position.Y = s_tree.AbsolutePosition.Y + (float)randY; 831 position.Y = s_tree.AbsolutePosition.Y + (float)randY;
750 832
751 if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 && 833 if (position.X > (m_scene.RegionInfo.RegionSizeX - 1) || position.X <= 0 ||
752 position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 && 834 position.Y > (m_scene.RegionInfo.RegionSizeY - 1) || position.Y <= 0)
753 Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range) 835 return;
754 {
755 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
756 836
757 CreateTree(uuid, copse, position); 837 randX = position.X - copse.m_seed_point.X;
758 } 838 randX *= randX;
839 randY = position.Y - copse.m_seed_point.Y;
840 randY *= randY;
841 randX += randY;
842
843 if(randX > copse.m_range * copse.m_range)
844 return;
845
846 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
847 CreateTree(uuid, copse, position, low);
759 } 848 }
760 849
761 private void CreateTree(UUID uuid, Copse copse, Vector3 position) 850 private void CreateTree(UUID uuid, Copse copse, Vector3 position, bool randomScale)
762 { 851 {
763
764 position.Z = (float)m_scene.Heightmap[(int)position.X, (int)position.Y]; 852 position.Z = (float)m_scene.Heightmap[(int)position.X, (int)position.Y];
765 if (position.Z >= copse.m_treeline_low && position.Z <= copse.m_treeline_high) 853 if (position.Z < copse.m_treeline_low || position.Z > copse.m_treeline_high)
766 { 854 return;
767 SceneObjectGroup tree = AddTree(uuid, UUID.Zero, copse.m_initial_scale, Quaternion.Identity, position, copse.m_tree_type, false);
768 855
769 tree.Name = copse.ToString(); 856 Vector3 scale = copse.m_initial_scale;
770 copse.m_trees.Add(tree.UUID); 857 if(randomScale)
771 tree.SendGroupFullUpdate(); 858 {
859 try
860 {
861 float t;
862 float r = (float)Util.RandomClass.NextDouble();
863 r *= (float)Util.RandomClass.NextDouble();
864 r *= (float)Util.RandomClass.NextDouble();
865
866 t = copse.m_maximum_scale.X / copse.m_initial_scale.X;
867 if(t < 1.0)
868 t = 1 / t;
869 t = t * r + 1.0f;
870 scale.X *= t;
871
872 t = copse.m_maximum_scale.Y / copse.m_initial_scale.Y;
873 if(t < 1.0)
874 t = 1 / t;
875 t = t * r + 1.0f;
876 scale.Y *= t;
877
878 t = copse.m_maximum_scale.Z / copse.m_initial_scale.Z;
879 if(t < 1.0)
880 t = 1 / t;
881 t = t * r + 1.0f;
882 scale.Z *= t;
883 }
884 catch
885 {
886 scale = copse.m_initial_scale;
887 }
772 } 888 }
889
890 SceneObjectGroup tree = AddTree(uuid, UUID.Zero, scale, Quaternion.Identity, position, copse.m_tree_type, false);
891 tree.Name = copse.ToString();
892 copse.m_trees.Add(tree.UUID);
893 tree.RootPart.ScheduleFullUpdate();
773 } 894 }
774 895
775 private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e) 896 private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e)
776 { 897 {
777 growTrees(); 898 if(!m_scene.IsRunning)
778 seedTrees(); 899 return;
779 killTrees(); 900
901 if(Monitor.TryEnter(mylock))
902 {
903 try
904 {
905 if(m_scene.LoginsEnabled )
906 {
907 growTrees();
908 seedTrees();
909 killTrees();
910 }
911 }
912 catch(Exception ex)
913 {
914 }
915 if(CalculateTrees != null)
916 CalculateTrees.Start();
917 Monitor.Exit(mylock);
918 }
780 } 919 }
781 } 920 }
782} 921}
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index fcbc1c5..a7b9213 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -1450,13 +1450,21 @@
1450 1450
1451 1451
1452[Trees] 1452[Trees]
1453 ; Enable this to allow the tree module to manage your sim trees, including growing, reproducing and dying 1453 ; enable the trees module. default true
1454 ; default is false 1454 enabled = true
1455
1456 ; active_trees allows module to change its trees in time.
1457 ; some will be deleted, others created and rest may grow
1458 ; default is false. You can change it with console comand tree active true | false later
1455 active_trees = false 1459 active_trees = false
1456 1460 ; the trees change execution time rate (in ms)
1457 ; Density of tree population 1461 update_rate = 1000
1458 tree_density = 1000.0 1462
1459 1463 ; allow the trees to grow.
1464 ; DANGER
1465 ; this option causes high network use on the order of
1466 ; NumberOfTrees * NumberAvatars * 1000 / update_rate udp packets per second
1467 allowGrow = false
1460 1468
1461[VectorRender] 1469[VectorRender]
1462 ; the font to use for rendering text (default: Arial) 1470 ; the font to use for rendering text (default: Arial)