aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/World/TreePopulator
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/World/TreePopulator')
-rw-r--r--OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs724
1 files changed, 433 insertions, 291 deletions
diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
index e4a3382..6e1f8bb 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,17 +43,15 @@ 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{
47 /// <summary> 50 /// <summary>
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");
@@ -60,7 +63,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
60 public string m_name; 63 public string m_name;
61 public Boolean m_frozen; 64 public Boolean m_frozen;
62 public Tree m_tree_type; 65 public Tree m_tree_type;
63 public int m_tree_quantity; 66 public int m_tree_quantity;
64 public float m_treeline_low; 67 public float m_treeline_low;
65 public float m_treeline_high; 68 public float m_treeline_high;
66 public Vector3 m_seed_point; 69 public Vector3 m_seed_point;
@@ -78,24 +81,24 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
78 { 81 {
79 } 82 }
80 83
81 public Copse(string fileName, Boolean planted) 84 public Copse(string fileName, Boolean planted)
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 { 184 {
181 m_active_trees = config.Configs["Trees"].GetBoolean("active_trees", m_active_trees); 185 m_enabled = moduleConfig.GetBoolean("enabled", m_enabled);
182 } 186 m_active_trees = moduleConfig.GetBoolean("active_trees", m_active_trees);
183 catch (Exception) 187 m_allowGrow = moduleConfig.GetBoolean("allowGrow", m_allowGrow);
184 { 188 m_update_ms = moduleConfig.GetDouble("update_rate", m_update_ms);
185 m_log.Debug("[TREES]: ini failure for active_trees - using default");
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,25 +282,57 @@ 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 lock(mylock)
271 { 286 {
272 if (cp.m_name == copsename && (!cp.m_frozen && freezeState || cp.m_frozen && !freezeState)) 287 foreach (Copse cp in m_copses)
273 { 288 {
274 cp.m_frozen = freezeState; 289 if (cp.m_name != copsename)
275 foreach (UUID tree in cp.m_trees) 290 continue;
291
292 if(!cp.m_frozen && freezeState || cp.m_frozen && !freezeState)
276 { 293 {
277 SceneObjectPart sop = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; 294 cp.m_frozen = freezeState;
278 sop.Name = (freezeState ? sop.Name.Replace("ATPM", "FTPM") : sop.Name.Replace("FTPM", "ATPM")); 295 List<UUID> losttrees = new List<UUID>();
279 sop.ParentGroup.HasGroupChanged = true; 296 foreach (UUID tree in cp.m_trees)
280 } 297 {
298 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
299 if(sog != null && !sog.IsDeleted)
300 {
301 SceneObjectPart sop = sog.RootPart;
302 string name = sop.Name;
303 if(freezeState)
304 {
305 if(name.StartsWith("FTPM"))
306 continue;
307 if(!name.StartsWith("ATPM"))
308 continue;
309 sop.Name = sop.Name.Replace("ATPM", "FTPM");
310 }
311 else
312 {
313 if(name.StartsWith("ATPM"))
314 continue;
315 if(!name.StartsWith("FTPM"))
316 continue;
317 sop.Name = sop.Name.Replace("FTPM", "ATPM");
318 }
319 sop.ParentGroup.HasGroupChanged = true;
320 sog.ScheduleGroupForFullUpdate();
321 }
322 else
323 losttrees.Add(tree);
324 }
325 foreach (UUID tree in losttrees)
326 cp.m_trees.Remove(tree);
281 327
282 m_log.InfoFormat("[TREES]: Activity for copse {0} is frozen {1}", copsename, freezeState); 328 m_log.InfoFormat("[TREES]: Activity for copse {0} is frozen {1}", copsename, freezeState);
283 return; 329 return;
284 } 330 }
285 else if (cp.m_name == copsename && (cp.m_frozen && freezeState || !cp.m_frozen && !freezeState)) 331 else
286 { 332 {
287 m_log.InfoFormat("[TREES]: Copse {0} is already in the requested freeze state", copsename); 333 m_log.InfoFormat("[TREES]: Copse {0} is already in the requested freeze state", copsename);
288 return; 334 return;
335 }
289 } 336 }
290 } 337 }
291 m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename); 338 m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename);
@@ -297,17 +344,21 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
297 344
298 m_log.InfoFormat("[TREES]: Loading copse definition...."); 345 m_log.InfoFormat("[TREES]: Loading copse definition....");
299 346
300 copse = new Copse(((string)args[0]), false); 347 lock(mylock)
301 foreach (Copse cp in m_copse)
302 { 348 {
303 if (cp.m_name == copse.m_name) 349 copse = new Copse(((string)args[0]), false);
304 { 350 {
305 m_log.InfoFormat("[TREES]: Copse: {0} is already defined - command failed", copse.m_name); 351 foreach (Copse cp in m_copses)
306 return; 352 {
353 if (cp.m_name == copse.m_name)
354 {
355 m_log.InfoFormat("[TREES]: Copse: {0} is already defined - command failed", copse.m_name);
356 return;
357 }
358 }
307 } 359 }
360 m_copses.Add(copse);
308 } 361 }
309
310 m_copse.Add(copse);
311 m_log.InfoFormat("[TREES]: Loaded copse: {0}", copse.ToString()); 362 m_log.InfoFormat("[TREES]: Loaded copse: {0}", copse.ToString());
312 } 363 }
313 364
@@ -318,20 +369,24 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
318 m_log.InfoFormat("[TREES]: New tree planting for copse {0}", copsename); 369 m_log.InfoFormat("[TREES]: New tree planting for copse {0}", copsename);
319 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; 370 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
320 371
321 foreach (Copse copse in m_copse) 372 lock(mylock)
322 { 373 {
323 if (copse.m_name == copsename) 374 foreach (Copse copse in m_copses)
324 { 375 {
325 if (!copse.m_planted) 376 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 { 377 {
334 m_log.InfoFormat("[TREES]: Copse {0} has already been planted", copsename); 378 if (!copse.m_planted)
379 {
380 // The first tree for a copse is created here
381 CreateTree(uuid, copse, copse.m_seed_point, true);
382 copse.m_planted = true;
383 return;
384 }
385 else
386 {
387 m_log.InfoFormat("[TREES]: Copse {0} has already been planted", copsename);
388 return;
389 }
335 } 390 }
336 } 391 }
337 } 392 }
@@ -376,45 +431,49 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
376 string copsename = ((string)args[0]).Trim(); 431 string copsename = ((string)args[0]).Trim();
377 Copse copseIdentity = null; 432 Copse copseIdentity = null;
378 433
379 foreach (Copse cp in m_copse) 434 lock(mylock)
380 { 435 {
381 if (cp.m_name == copsename) 436 foreach (Copse cp in m_copses)
382 { 437 {
383 copseIdentity = cp; 438 if (cp.m_name == copsename)
439 {
440 copseIdentity = cp;
441 }
384 } 442 }
385 }
386 443
387 if (copseIdentity != null) 444 if (copseIdentity != null)
388 {
389 foreach (UUID tree in copseIdentity.m_trees)
390 { 445 {
391 if (m_scene.Entities.ContainsKey(tree)) 446 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 { 447 {
399 m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); 448 if (m_scene.Entities.ContainsKey(tree))
449 {
450 SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
451 // Delete tree and alert clients (not silent)
452 m_scene.DeleteSceneObject(selectedTree.ParentGroup, false);
453 }
454 else
455 {
456 m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
457 }
400 } 458 }
459 copseIdentity.m_trees = null;
460 m_copses.Remove(copseIdentity);
461 m_log.InfoFormat("[TREES]: Copse {0} has been removed", copsename);
462 }
463 else
464 {
465 m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename);
401 } 466 }
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 } 467 }
410 } 468 }
411 469
412 private void HandleTreeStatistics(Object[] args) 470 private void HandleTreeStatistics(Object[] args)
413 { 471 {
414 m_log.InfoFormat("[TREES]: Activity State: {0}; Update Rate: {1}", m_active_trees, m_update_ms); 472 m_log.InfoFormat("[TREES]: region {0}:", m_scene.Name);
415 foreach (Copse cp in m_copse) 473 m_log.InfoFormat("[TREES]: Activity State: {0}; Update Rate: {1}", m_active_trees, m_update_ms);
474 foreach (Copse cp in m_copses)
416 { 475 {
417 m_log.InfoFormat("[TREES]: Copse {0}; {1} trees; frozen {2}", cp.m_name, cp.m_trees.Count, cp.m_frozen); 476 m_log.InfoFormat("[TREES]: Copse {0}; {1} trees; frozen {2}", cp.m_name, cp.m_trees.Count, cp.m_frozen);
418 } 477 }
419 } 478 }
420 479
@@ -442,7 +501,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
442 treeRateCommand.AddArgument("updateRate", "The required update rate (minimum 1000.0)", "Double"); 501 treeRateCommand.AddArgument("updateRate", "The required update rate (minimum 1000.0)", "Double");
443 502
444 Command treeReloadCommand = 503 Command treeReloadCommand =
445 new Command("reload", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeReload, "Reload copse definitions from the in-scene trees"); 504 new Command("reload", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeReload, "Reload copses from the in-scene trees");
446 505
447 Command treeRemoveCommand = 506 Command treeRemoveCommand =
448 new Command("remove", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeRemove, "Remove a copse definition and all its in-scene trees"); 507 new Command("remove", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeRemove, "Remove a copse definition and all its in-scene trees");
@@ -499,34 +558,17 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
499 treeShape.Scale = scale; 558 treeShape.Scale = scale;
500 treeShape.State = (byte)treeType; 559 treeShape.State = (byte)treeType;
501 560
502 return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape); 561 SceneObjectGroup sog = new SceneObjectGroup(uuid, position, rotation, treeShape);
503 } 562 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 563
524 rootPart.AddFlag(PrimFlags.Phantom); 564 rootPart.AddFlag(PrimFlags.Phantom);
525 565
526 m_scene.AddNewSceneObject(sceneObject, true); 566 sog.SetGroup(groupID, null);
527 sceneObject.SetGroup(groupID, null); 567 m_scene.AddNewSceneObject(sog, true, false);
528 568 sog.IsSelected = false;
529 return sceneObject; 569 rootPart.IsSelected = false;
570 sog.InvalidateEffectivePerms();
571 return sog;
530 } 572 }
531 573
532 #endregion 574 #endregion
@@ -569,26 +611,27 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
569 611
570 private void ReloadCopse() 612 private void ReloadCopse()
571 { 613 {
572 m_copse = new List<Copse>(); 614 m_copses = new List<Copse>();
573 615
574 EntityBase[] objs = m_scene.GetEntities(); 616 List<SceneObjectGroup> grps = m_scene.GetSceneObjectGroups();
575 foreach (EntityBase obj in objs) 617 foreach (SceneObjectGroup grp in grps)
576 { 618 {
577 if (obj is SceneObjectGroup) 619 if(grp.RootPart.Shape.PCode != (byte)PCode.NewTree && grp.RootPart.Shape.PCode != (byte)PCode.Tree)
578 { 620 continue;
579 SceneObjectGroup grp = (SceneObjectGroup)obj;
580 621
581 if (grp.Name.Length > 5 && (grp.Name.Substring(0, 5) == "ATPM:" || grp.Name.Substring(0, 5) == "FTPM:")) 622 if (grp.Name.Length > 5 && (grp.Name.Substring(0, 5) == "ATPM:" || grp.Name.Substring(0, 5) == "FTPM:"))
623 {
624 // Create a new copse definition or add uuid to an existing definition
625 try
582 { 626 {
583 // Create a new copse definition or add uuid to an existing definition 627 Boolean copsefound = false;
584 try 628 Copse grpcopse = new Copse(grp.Name);
585 {
586 Boolean copsefound = false;
587 Copse copse = new Copse(grp.Name);
588 629
589 foreach (Copse cp in m_copse) 630 lock(mylock)
631 {
632 foreach (Copse cp in m_copses)
590 { 633 {
591 if (cp.m_name == copse.m_name) 634 if (cp.m_name == grpcopse.m_name)
592 { 635 {
593 copsefound = true; 636 copsefound = true;
594 cp.m_trees.Add(grp.UUID); 637 cp.m_trees.Add(grp.UUID);
@@ -598,15 +641,15 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
598 641
599 if (!copsefound) 642 if (!copsefound)
600 { 643 {
601 m_log.InfoFormat("[TREES]: Found copse {0}", grp.Name); 644 m_log.InfoFormat("[TREES]: adding copse {0}", grpcopse.m_name);
602 m_copse.Add(copse); 645 grpcopse.m_trees.Add(grp.UUID);
603 copse.m_trees.Add(grp.UUID); 646 m_copses.Add(grpcopse);
604 } 647 }
605 } 648 }
606 catch 649 }
607 { 650 catch
608 m_log.InfoFormat("[TREES]: Ill formed copse definition {0} - ignoring", grp.Name); 651 {
609 } 652 m_log.InfoFormat("[TREES]: Ill formed copse definition {0} - ignoring", grp.Name);
610 } 653 }
611 } 654 }
612 } 655 }
@@ -617,166 +660,265 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
617 { 660 {
618 if (activeYN) 661 if (activeYN)
619 { 662 {
620 CalculateTrees = new Timer(m_update_ms); 663 if(CalculateTrees == null)
664 CalculateTrees = new Timer(m_update_ms);
621 CalculateTrees.Elapsed += CalculateTrees_Elapsed; 665 CalculateTrees.Elapsed += CalculateTrees_Elapsed;
666 CalculateTrees.AutoReset = false;
622 CalculateTrees.Start(); 667 CalculateTrees.Start();
623 } 668 }
624 else 669 else
625 { 670 {
626 CalculateTrees.Stop(); 671 CalculateTrees.Stop();
627 } 672 }
628 } 673 }
629 674
630 private void growTrees() 675 private void growTrees()
631 { 676 {
632 foreach (Copse copse in m_copse) 677 if(!m_allowGrow)
678 return;
679
680 foreach (Copse copse in m_copses)
633 { 681 {
634 if (!copse.m_frozen) 682 if (copse.m_frozen)
683 continue;
684
685 if(copse.m_trees.Count == 0)
686 continue;
687
688 float maxscale = copse.m_maximum_scale.Z;
689 float ratescale = 1.0f;
690 List<UUID> losttrees = new List<UUID>();
691 foreach (UUID tree in copse.m_trees)
635 { 692 {
636 foreach (UUID tree in copse.m_trees) 693 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 694
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) 695 if (sog != null && !sog.IsDeleted)
643 { 696 {
644 s_tree.Scale += copse.m_rate; 697 SceneObjectPart s_tree = sog.RootPart;
645 s_tree.ParentGroup.HasGroupChanged = true; 698 if (s_tree.Scale.Z < maxscale)
646 s_tree.ScheduleFullUpdate();
647 }
648 }
649 else
650 { 699 {
651 m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); 700 ratescale = (float)Util.RandomClass.NextDouble();
701 if(ratescale < 0.2f)
702 ratescale = 0.2f;
703 s_tree.Scale += copse.m_rate * ratescale;
704 sog.HasGroupChanged = true;
705 s_tree.ScheduleFullUpdate();
652 } 706 }
653 } 707 }
708 else
709 losttrees.Add(tree);
654 } 710 }
711
712 foreach (UUID tree in losttrees)
713 copse.m_trees.Remove(tree);
655 } 714 }
656 } 715 }
657 716
658 private void seedTrees() 717 private void seedTrees()
659 { 718 {
660 foreach (Copse copse in m_copse) 719 foreach (Copse copse in m_copses)
661 { 720 {
662 if (!copse.m_frozen) 721 if (copse.m_frozen)
722 continue;
723
724 if(copse.m_trees.Count == 0)
725 return;
726
727 bool low = copse.m_trees.Count < (int)(copse.m_tree_quantity * 0.8f);
728
729 if (!low && Util.RandomClass.NextDouble() < 0.75)
730 return;
731
732 int maxbirths = (int)(copse.m_tree_quantity) - copse.m_trees.Count;
733 if(maxbirths <= 1)
734 return;
735
736 if(maxbirths > 20)
737 maxbirths = 20;
738
739 float minscale = 0;
740 if(!low && m_allowGrow)
741 minscale = copse.m_maximum_scale.Z * 0.75f;;
742
743 int i = 0;
744 UUID[] current = copse.m_trees.ToArray();
745 while(--maxbirths > 0)
663 { 746 {
664 foreach (UUID tree in copse.m_trees) 747 if(current.Length > 1)
748 i = Util.RandomClass.Next(current.Length -1);
749
750 UUID tree = current[i];
751 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
752
753 if (sog != null && !sog.IsDeleted)
665 { 754 {
666 if (m_scene.Entities.ContainsKey(tree)) 755 SceneObjectPart s_tree = sog.RootPart;
667 {
668 SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
669 756
670 if (copse.m_trees.Count < copse.m_tree_quantity) 757 // Tree has grown enough to seed if it has grown by at least 25% of seeded to full grown height
671 { 758 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 759 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 } 760 }
687 } 761 else if(copse.m_trees.Contains(tree))
762 copse.m_trees.Remove(tree);
763 }
688 } 764 }
689 } 765 }
690 766
691 private void killTrees() 767 private void killTrees()
692 { 768 {
693 foreach (Copse copse in m_copse) 769 foreach (Copse copse in m_copses)
694 { 770 {
695 if (!copse.m_frozen && copse.m_trees.Count >= copse.m_tree_quantity) 771 if (copse.m_frozen)
696 { 772 continue;
697 foreach (UUID tree in copse.m_trees)
698 {
699 double killLikelyhood = 0.0;
700 773
701 if (m_scene.Entities.ContainsKey(tree)) 774 if (Util.RandomClass.NextDouble() < 0.25)
702 { 775 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 776
718 double pickedTreeDistance = Vector3.Distance(pickedTree.AbsolutePosition, selectedTree.AbsolutePosition); 777 int maxbdeaths = copse.m_trees.Count - (int)(copse.m_tree_quantity * .98f) ;
778 if(maxbdeaths < 1)
779 return;
719 780
720 killLikelyhood += (selectedTreeScale / (pickedTreeScale * pickedTreeDistance)) * 0.1; 781 float odds;
721 } 782 float scale = 1.0f / copse.m_maximum_scale.Z;
722 }
723 783
724 if (Util.RandomClass.NextDouble() < killLikelyhood) 784 int ntries = maxbdeaths * 4;
725 { 785 while(ntries-- > 0 )
726 // Delete tree and alert clients (not silent) 786 {
727 m_scene.DeleteSceneObject(selectedTree.ParentGroup, false); 787 int next = 0;
728 copse.m_trees.Remove(selectedTree.ParentGroup.UUID); 788 if (copse.m_trees.Count > 1)
729 break; 789 next = Util.RandomClass.Next(copse.m_trees.Count - 1);
730 } 790 UUID tree = copse.m_trees[next];
791 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
792 if (sog != null && !sog.IsDeleted)
793 {
794 if(m_allowGrow)
795 {
796 odds = sog.RootPart.Scale.Z * scale;
797 odds = odds * odds * odds;
798 odds *= (float)Util.RandomClass.NextDouble();
731 } 799 }
732 else 800 else
733 { 801 {
734 m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); 802 odds = (float)Util.RandomClass.NextDouble();
803 odds = odds * odds * odds;
735 } 804 }
805
806 if(odds > 0.9f)
807 {
808 m_scene.DeleteSceneObject(sog, false);
809 if(maxbdeaths <= 0)
810 break;
811 }
812 }
813 else
814 {
815 copse.m_trees.Remove(tree);
816 if(copse.m_trees.Count - (int)(copse.m_tree_quantity * .98f) <= 0 )
817 break;
736 } 818 }
737 } 819 }
738 } 820 }
739 } 821 }
740 822
741 private void SpawnChild(Copse copse, SceneObjectPart s_tree) 823 private void SpawnChild(Copse copse, SceneObjectPart s_tree, bool low)
742 { 824 {
743 Vector3 position = new Vector3(); 825 Vector3 position = new Vector3();
744 826
745 double randX = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); 827 float randX = copse.m_maximum_scale.X * 1.25f;
746 double randY = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); 828 float randY = copse.m_maximum_scale.Y * 1.25f;
747 829
830 float r = (float)Util.RandomClass.NextDouble();
831 randX *= 2.0f * r - 1.0f;
748 position.X = s_tree.AbsolutePosition.X + (float)randX; 832 position.X = s_tree.AbsolutePosition.X + (float)randX;
833
834 r = (float)Util.RandomClass.NextDouble();
835 randY *= 2.0f * r - 1.0f;
749 position.Y = s_tree.AbsolutePosition.Y + (float)randY; 836 position.Y = s_tree.AbsolutePosition.Y + (float)randY;
750 837
751 if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 && 838 if (position.X > (m_scene.RegionInfo.RegionSizeX - 1) || position.X <= 0 ||
752 position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 && 839 position.Y > (m_scene.RegionInfo.RegionSizeY - 1) || position.Y <= 0)
753 Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range) 840 return;
754 {
755 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
756 841
757 CreateTree(uuid, copse, position); 842 randX = position.X - copse.m_seed_point.X;
758 } 843 randX *= randX;
844 randY = position.Y - copse.m_seed_point.Y;
845 randY *= randY;
846 randX += randY;
847
848 if(randX > copse.m_range * copse.m_range)
849 return;
850
851 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
852 CreateTree(uuid, copse, position, low);
759 } 853 }
760 854
761 private void CreateTree(UUID uuid, Copse copse, Vector3 position) 855 private void CreateTree(UUID uuid, Copse copse, Vector3 position, bool randomScale)
762 { 856 {
763
764 position.Z = (float)m_scene.Heightmap[(int)position.X, (int)position.Y]; 857 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) 858 if (position.Z < copse.m_treeline_low || position.Z > copse.m_treeline_high)
766 { 859 return;
767 SceneObjectGroup tree = AddTree(uuid, UUID.Zero, copse.m_initial_scale, Quaternion.Identity, position, copse.m_tree_type, false);
768 860
769 tree.Name = copse.ToString(); 861 Vector3 scale = copse.m_initial_scale;
770 copse.m_trees.Add(tree.UUID); 862 if(randomScale)
771 tree.SendGroupFullUpdate(); 863 {
864 try
865 {
866 float t;
867 float r = (float)Util.RandomClass.NextDouble();
868 r *= (float)Util.RandomClass.NextDouble();
869 r *= (float)Util.RandomClass.NextDouble();
870
871 t = copse.m_maximum_scale.X / copse.m_initial_scale.X;
872 if(t < 1.0)
873 t = 1 / t;
874 t = t * r + 1.0f;
875 scale.X *= t;
876
877 t = copse.m_maximum_scale.Y / copse.m_initial_scale.Y;
878 if(t < 1.0)
879 t = 1 / t;
880 t = t * r + 1.0f;
881 scale.Y *= t;
882
883 t = copse.m_maximum_scale.Z / copse.m_initial_scale.Z;
884 if(t < 1.0)
885 t = 1 / t;
886 t = t * r + 1.0f;
887 scale.Z *= t;
888 }
889 catch
890 {
891 scale = copse.m_initial_scale;
892 }
772 } 893 }
894
895 SceneObjectGroup tree = AddTree(uuid, UUID.Zero, scale, Quaternion.Identity, position, copse.m_tree_type, false);
896 tree.Name = copse.ToString();
897 copse.m_trees.Add(tree.UUID);
898 tree.RootPart.ScheduleFullUpdate();
773 } 899 }
774 900
775 private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e) 901 private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e)
776 { 902 {
777 growTrees(); 903 if(!m_scene.IsRunning)
778 seedTrees(); 904 return;
779 killTrees(); 905
906 if(Monitor.TryEnter(mylock))
907 {
908 try
909 {
910 if(m_scene.LoginsEnabled )
911 {
912 growTrees();
913 seedTrees();
914 killTrees();
915 }
916 }
917 catch { }
918 if(CalculateTrees != null)
919 CalculateTrees.Start();
920 Monitor.Exit(mylock);
921 }
780 } 922 }
781 } 923 }
782} 924}