From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001
From: onefang
Date: Sun, 19 May 2019 21:24:15 +1000
Subject: Dump OpenSim 0.9.0.1 into it's own branch.
---
.../World/AutoBackup/AutoBackupModule.cs | 791 ++++++---------------
.../World/AutoBackup/AutoBackupModuleState.cs | 70 +-
.../World/MoneyModule/SampleMoneyModule.cs | 156 ++--
.../Region/OptionalModules/World/NPC/NPCAvatar.cs | 181 ++++-
.../Region/OptionalModules/World/NPC/NPCModule.cs | 99 ++-
.../World/NPC/Tests/NPCModuleTests.cs | 8 +-
.../World/SceneCommands/SceneCommandsModule.cs | 122 +---
.../World/TreePopulator/TreePopulatorModule.cs | 724 +++++++++++--------
8 files changed, 1006 insertions(+), 1145 deletions(-)
(limited to 'OpenSim/Region/OptionalModules/World')
diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
index ceb3332..a14d819 100644
--- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
+++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
@@ -59,70 +59,58 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
///
///
/// Config Settings Documentation.
- /// Each configuration setting can be specified in two places: OpenSim.ini or Regions.ini.
- /// If specified in Regions.ini, the settings should be within the region's section name.
- /// If specified in OpenSim.ini, the settings should be within the [AutoBackupModule] section.
+ /// Configuration setting can be specified in two places: OpenSim.ini and/or Regions.ini.
+ ///
+ /// OpenSim.ini only settings section [AutoBackupModule]
+ /// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module.
+ /// if false module is disable and all rest is ignored
+ /// AutoBackupInterval: Double, non-negative value. Default: 720 (12 hours).
+ /// The number of minutes between each backup attempt.
+ /// AutoBackupDir: String. Default: "." (the current directory).
+ /// A directory (absolute or relative) where backups should be saved.
+ /// AutoBackupKeepFilesForDays remove files older than this number of days. 0 disables
+ ///
+ /// Next can be set on OpenSim.ini, as default, and or per region in Regions.ini
/// Region-specific settings take precedence.
///
- /// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module. This setting does not support per-region basis.
- /// All other settings under [AutoBackupModule] are ignored if AutoBackupModuleEnabled is false, even per-region settings!
- /// AutoBackup: True/False. Default: False. If True, activate auto backup functionality.
- /// This is the only required option for enabling auto-backup; the other options have sane defaults.
- /// If False for a particular region, the auto-backup module becomes a no-op for the region, and all other AutoBackup* settings are ignored.
- /// If False globally (the default), only regions that specifically override it in Regions.ini will get AutoBackup functionality.
- /// AutoBackupInterval: Double, non-negative value. Default: 720 (12 hours).
- /// The number of minutes between each backup attempt.
- /// If a negative or zero value is given, it is equivalent to setting AutoBackup = False.
- /// AutoBackupBusyCheck: True/False. Default: True.
- /// If True, we will only take an auto-backup if a set of conditions are met.
- /// These conditions are heuristics to try and avoid taking a backup when the sim is busy.
+ /// AutoBackup: True/False. Default: False. If True, activate auto backup functionality.
+ /// controls backup per region, with default optionaly set on OpenSim.ini
+
/// AutoBackupSkipAssets
/// If true, assets are not saved to the oar file. Considerably reduces impact on simulator when backing up. Intended for when assets db is backed up separately
/// AutoBackupKeepFilesForDays
/// Backup files older than this value (in days) are deleted during the current backup process, 0 will disable this and keep all backup files indefinitely
- /// AutoBackupScript: String. Default: not specified (disabled).
+ /// AutoBackupScript: String. Default: not specified (disabled).
/// File path to an executable script or binary to run when an automatic backup is taken.
/// The file should really be (Windows) an .exe or .bat, or (Linux/Mac) a shell script or binary.
/// Trying to "run" directories, or things with weird file associations on Win32, might cause unexpected results!
- /// argv[1] of the executed file/script will be the file name of the generated OAR.
+ /// argv[1] of the executed file/script will be the file name of the generated OAR.
/// If the process can't be spawned for some reason (file not found, no execute permission, etc), write a warning to the console.
/// AutoBackupNaming: string. Default: Time.
/// One of three strings (case insensitive):
/// "Time": Current timestamp is appended to file name. An existing file will never be overwritten.
- /// "Sequential": A number is appended to the file name. So if RegionName_x.oar exists, we'll save to RegionName_{x+1}.oar next. An existing file will never be overwritten.
- /// "Overwrite": Always save to file named "${AutoBackupDir}/RegionName.oar", even if we have to overwrite an existing file.
- /// AutoBackupDir: String. Default: "." (the current directory).
- /// A directory (absolute or relative) where backups should be saved.
- /// AutoBackupDilationThreshold: float. Default: 0.5. Lower bound on time dilation required for BusyCheck heuristics to pass.
- /// If the time dilation is below this value, don't take a backup right now.
- /// AutoBackupAgentThreshold: int. Default: 10. Upper bound on # of agents in region required for BusyCheck heuristics to pass.
- /// If the number of agents is greater than this value, don't take a backup right now
- /// Save memory by setting low initial capacities. Minimizes impact in common cases of all regions using same interval, and instances hosting 1 ~ 4 regions.
- /// Also helps if you don't want AutoBackup at all.
+ /// "Sequential": A number is appended to the file name. So if RegionName_x.oar exists, we'll save to RegionName_{x+1}.oar next. An existing file will never be overwritten.
+ /// "Overwrite": Always save to file named "${AutoBackupDir}/RegionName.oar", even if we have to overwrite an existing file.
///
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AutoBackupModule")]
public class AutoBackupModule : ISharedRegionModule
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private readonly Dictionary m_pendingSaves = new Dictionary(1);
private readonly AutoBackupModuleState m_defaultState = new AutoBackupModuleState();
private readonly Dictionary m_states =
new Dictionary(1);
- private readonly Dictionary> m_timerMap =
- new Dictionary>(1);
- private readonly Dictionary m_timers = new Dictionary(1);
private delegate T DefaultGetter(string settingName, T defaultValue);
private bool m_enabled;
private ICommandConsole m_console;
private List m_Scenes = new List ();
-
-
- ///
- /// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState!
- ///
- private bool m_closed;
+ private Timer m_masterTimer;
+ private bool m_busy;
+ private int m_KeepFilesForDays = -1;
+ private string m_backupDir;
+ private bool m_doneFirst;
+ private double m_baseInterval;
private IConfigSource m_configSource;
@@ -159,36 +147,38 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
void IRegionModuleBase.Initialise(IConfigSource source)
{
// Determine if we have been enabled at all in OpenSim.ini -- this is part and parcel of being an optional module
- this.m_configSource = source;
+ m_configSource = source;
IConfig moduleConfig = source.Configs["AutoBackupModule"];
if (moduleConfig == null)
{
- this.m_enabled = false;
+ m_enabled = false;
return;
}
- else
- {
- this.m_enabled = moduleConfig.GetBoolean("AutoBackupModuleEnabled", false);
- if (this.m_enabled)
- {
- m_log.Info("[AUTO BACKUP]: AutoBackupModule enabled");
- }
- else
- {
- return;
- }
- }
- Timer defTimer = new Timer(43200000);
- this.m_defaultState.Timer = defTimer;
- this.m_timers.Add(43200000, defTimer);
- defTimer.Elapsed += this.HandleElapsed;
- defTimer.AutoReset = true;
- defTimer.Start();
+ m_enabled = moduleConfig.GetBoolean("AutoBackupModuleEnabled", false);
+ if(!m_enabled)
+ return;
+
+ ParseDefaultConfig(moduleConfig);
+ if(!m_enabled)
+ return;
+
+ m_log.Debug("[AUTO BACKUP]: Default config:");
+ m_log.Debug(m_defaultState.ToString());
+
+ m_log.Info("[AUTO BACKUP]: AutoBackupModule enabled");
+ m_masterTimer = new Timer();
+ m_masterTimer.Interval = m_baseInterval;
+ m_masterTimer.Elapsed += HandleElapsed;
+ m_masterTimer.AutoReset = false;
+
+ m_console = MainConsole.Instance;
- AutoBackupModuleState abms = this.ParseConfig(null, true);
- m_log.Debug("[AUTO BACKUP]: Here is the default config:");
- m_log.Debug(abms.ToString());
+ m_console.Commands.AddCommand (
+ "AutoBackup", true, "dooarbackup",
+ "dooarbackup | ALL",
+ "saves the single region to a oar or ALL regions in instance to oars, using same settings as AutoBackup. Note it restarts time interval", DoBackup);
+ m_busy = true;
}
///
@@ -196,13 +186,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
///
void IRegionModuleBase.Close()
{
- if (!this.m_enabled)
- {
+ if (!m_enabled)
return;
- }
// We don't want any timers firing while the sim's coming down; strange things may happen.
- this.StopAllTimers();
+ m_masterTimer.Dispose();
}
///
@@ -211,18 +199,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
///
void IRegionModuleBase.AddRegion (Scene scene)
{
- if (!this.m_enabled) {
+ if (!m_enabled)
return;
- }
- lock (m_Scenes) {
- m_Scenes.Add (scene);
- }
- m_console = MainConsole.Instance;
- m_console.Commands.AddCommand (
- "AutoBackup", false, "dobackup",
- "dobackup",
- "do backup.", DoBackup);
+ lock (m_Scenes)
+ m_Scenes.Add (scene);
}
///
@@ -231,28 +212,14 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// The scene (region) to stop performing AutoBackup on.
void IRegionModuleBase.RemoveRegion(Scene scene)
{
- if (!this.m_enabled)
- {
+ if (m_enabled)
return;
- }
- m_Scenes.Remove (scene);
- if (this.m_states.ContainsKey(scene))
- {
- AutoBackupModuleState abms = this.m_states[scene];
- // Remove this scene out of the timer map list
- Timer timer = abms.Timer;
- List list = this.m_timerMap[timer];
- list.Remove(scene);
-
- // Shut down the timer if this was the last scene for the timer
- if (list.Count == 0)
- {
- this.m_timerMap.Remove(timer);
- this.m_timers.Remove(timer.Interval);
- timer.Close();
- }
- this.m_states.Remove(scene);
+ lock(m_Scenes)
+ {
+ if (m_states.ContainsKey(scene))
+ m_states.Remove(scene);
+ m_Scenes.Remove(scene);
}
}
@@ -263,22 +230,29 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// The scene to (possibly) perform AutoBackup on.
void IRegionModuleBase.RegionLoaded(Scene scene)
{
- if (!this.m_enabled)
- {
+ if (!m_enabled)
return;
- }
// This really ought not to happen, but just in case, let's pretend it didn't...
if (scene == null)
- {
return;
- }
- AutoBackupModuleState abms = this.ParseConfig(scene, false);
- m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName);
- m_log.Debug((abms == null ? "DEFAULT" : abms.ToString()));
+ AutoBackupModuleState abms = ParseConfig(scene);
+ if(abms == null)
+ {
+ m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName);
+ m_log.Debug("DEFAULT");
+ abms = new AutoBackupModuleState(m_defaultState);
+ }
+ else
+ {
+ m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName);
+ m_log.Debug(abms.ToString());
+ }
m_states.Add(scene, abms);
+ m_busy = false;
+ m_masterTimer.Start();
}
///
@@ -292,356 +266,174 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
private void DoBackup (string module, string[] args)
{
- if (args.Length != 2) {
- MainConsole.Instance.OutputFormat ("Usage: dobackup ");
+ if (!m_enabled)
return;
- }
- bool found = false;
- string name = args [1];
- lock (m_Scenes) {
- foreach (Scene s in m_Scenes) {
- string test = s.Name.ToString ();
- if (test == name) {
- found = true;
- DoRegionBackup (s);
- }
- }
- if (!found) {
- MainConsole.Instance.OutputFormat ("No such region {0}. Nothing to backup", name);
- }
- }
- }
- ///
- /// Set up internal state for a given scene. Fairly complex code.
- /// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene.
- ///
- /// The scene to look at.
- /// Whether this call is intended to figure out what we consider the "default" config (applied to all regions unless overridden by per-region settings).
- /// An AutoBackupModuleState contains most information you should need to know relevant to auto-backup, as applicable to a single region.
- private AutoBackupModuleState ParseConfig(IScene scene, bool parseDefault)
- {
- string sRegionName;
- string sRegionLabel;
-// string prepend;
- AutoBackupModuleState state;
-
- if (parseDefault)
- {
- sRegionName = null;
- sRegionLabel = "DEFAULT";
-// prepend = "";
- state = this.m_defaultState;
- }
- else
- {
- sRegionName = scene.RegionInfo.RegionName;
- sRegionLabel = sRegionName;
-// prepend = sRegionName + ".";
- state = null;
- }
-
- // Read the config settings and set variables.
- IConfig regionConfig = (scene != null ? scene.Config.Configs[sRegionName] : null);
- IConfig config = this.m_configSource.Configs["AutoBackupModule"];
- if (config == null)
+ if (args.Length != 2)
{
- // defaultState would be disabled too if the section doesn't exist.
- state = this.m_defaultState;
- return state;
- }
-
- bool tmpEnabled = ResolveBoolean("AutoBackup", this.m_defaultState.Enabled, config, regionConfig);
- if (state == null && tmpEnabled != this.m_defaultState.Enabled)
- //Varies from default state
- {
- state = new AutoBackupModuleState();
+ MainConsole.Instance.OutputFormat ("Usage: dooarbackup ");
+ return;
}
- if (state != null)
+ if(m_busy)
{
- state.Enabled = tmpEnabled;
+ MainConsole.Instance.OutputFormat ("Already doing a backup, please try later");
+ return;
}
- // If you don't want AutoBackup, we stop.
- if ((state == null && !this.m_defaultState.Enabled) || (state != null && !state.Enabled))
- {
- return state;
- }
- else
- {
- m_log.Info("[AUTO BACKUP]: Region " + sRegionLabel + " is AutoBackup ENABLED.");
- }
+ m_masterTimer.Stop();
+ m_busy = true;
- // Borrow an existing timer if one exists for the same interval; otherwise, make a new one.
- double interval =
- this.ResolveDouble("AutoBackupInterval", this.m_defaultState.IntervalMinutes,
- config, regionConfig) * 60000.0;
- if (state == null && interval != this.m_defaultState.IntervalMinutes * 60000.0)
- {
- state = new AutoBackupModuleState();
- }
+ bool found = false;
+ string name = args [1];
+ Scene[] scenes;
+ lock (m_Scenes)
+ scenes = m_Scenes.ToArray();
- if (this.m_timers.ContainsKey(interval))
- {
- if (state != null)
- {
- state.Timer = this.m_timers[interval];
- }
- m_log.Debug("[AUTO BACKUP]: Reusing timer for " + interval + " msec for region " +
- sRegionLabel);
- }
- else
- {
- // 0 or negative interval == do nothing.
- if (interval <= 0.0 && state != null)
- {
- state.Enabled = false;
- return state;
- }
- if (state == null)
- {
- state = new AutoBackupModuleState();
- }
- Timer tim = new Timer(interval);
- state.Timer = tim;
- //Milliseconds -> minutes
- this.m_timers.Add(interval, tim);
- tim.Elapsed += this.HandleElapsed;
- tim.AutoReset = true;
- tim.Start();
- }
+ if(scenes == null)
+ return;
- // Add the current region to the list of regions tied to this timer.
- if (scene != null)
+ Scene s;
+ try
{
- if (state != null)
+ if(name == "ALL")
{
- if (this.m_timerMap.ContainsKey(state.Timer))
+ for(int i = 0; i < scenes.Length; i++)
{
- this.m_timerMap[state.Timer].Add(scene);
- }
- else
- {
- List scns = new List(1);
- scns.Add(scene);
- this.m_timerMap.Add(state.Timer, scns);
+ s = scenes[i];
+ DoRegionBackup(s);
+ if (!m_enabled)
+ return;
}
+ return;
}
- else
+
+ for(int i = 0; i < scenes.Length; i++)
{
- if (this.m_timerMap.ContainsKey(this.m_defaultState.Timer))
+ s = scenes[i];
+ if (s.Name == name)
{
- this.m_timerMap[this.m_defaultState.Timer].Add(scene);
- }
- else
- {
- List scns = new List(1);
- scns.Add(scene);
- this.m_timerMap.Add(this.m_defaultState.Timer, scns);
+ found = true;
+ DoRegionBackup(s);
+ break;
}
}
}
-
- bool tmpBusyCheck = ResolveBoolean("AutoBackupBusyCheck",
- this.m_defaultState.BusyCheck, config, regionConfig);
- if (state == null && tmpBusyCheck != this.m_defaultState.BusyCheck)
+ catch { }
+ finally
{
- state = new AutoBackupModuleState();
- }
+ if (m_enabled)
+ m_masterTimer.Start();
+ m_busy = false;
+ }
+ if (!found)
+ MainConsole.Instance.OutputFormat ("No such region {0}. Nothing to backup", name);
+ }
- if (state != null)
- {
- state.BusyCheck = tmpBusyCheck;
- }
+ private void ParseDefaultConfig(IConfig config)
+ {
- // Included Option To Skip Assets
- bool tmpSkipAssets = ResolveBoolean("AutoBackupSkipAssets",
- this.m_defaultState.SkipAssets, config, regionConfig);
- if (state == null && tmpSkipAssets != this.m_defaultState.SkipAssets)
+ m_backupDir = ".";
+ string backupDir = config.GetString("AutoBackupDir", ".");
+ if (backupDir != ".")
{
- state = new AutoBackupModuleState();
+ try
+ {
+ DirectoryInfo dirinfo = new DirectoryInfo(backupDir);
+ if (!dirinfo.Exists)
+ dirinfo.Create();
+ }
+ catch (Exception e)
+ {
+ m_enabled = false;
+ m_log.WarnFormat("[AUTO BACKUP]: Error accessing backup folder {0}. Module disabled. {1}",
+ backupDir, e);
+ return;
+ }
}
+ m_backupDir = backupDir;
- if (state != null)
- {
- state.SkipAssets = tmpSkipAssets;
- }
+ double interval = config.GetDouble("AutoBackupInterval", 720);
+ interval *= 60000.0;
+ m_baseInterval = interval;
// How long to keep backup files in days, 0 Disables this feature
- int tmpKeepFilesForDays = ResolveInt("AutoBackupKeepFilesForDays",
- this.m_defaultState.KeepFilesForDays, config, regionConfig);
- if (state == null && tmpKeepFilesForDays != this.m_defaultState.KeepFilesForDays)
- {
- state = new AutoBackupModuleState();
- }
+ m_KeepFilesForDays = config.GetInt("AutoBackupKeepFilesForDays",m_KeepFilesForDays);
- if (state != null)
- {
- state.KeepFilesForDays = tmpKeepFilesForDays;
- }
+ m_defaultState.Enabled = config.GetBoolean("AutoBackup", m_defaultState.Enabled);
+
+ m_defaultState.SkipAssets = config.GetBoolean("AutoBackupSkipAssets",m_defaultState.SkipAssets);
// Set file naming algorithm
- string stmpNamingType = ResolveString("AutoBackupNaming",
- this.m_defaultState.NamingType.ToString(), config, regionConfig);
+ string stmpNamingType = config.GetString("AutoBackupNaming", m_defaultState.NamingType.ToString());
NamingType tmpNamingType;
if (stmpNamingType.Equals("Time", StringComparison.CurrentCultureIgnoreCase))
- {
tmpNamingType = NamingType.Time;
- }
else if (stmpNamingType.Equals("Sequential", StringComparison.CurrentCultureIgnoreCase))
- {
tmpNamingType = NamingType.Sequential;
- }
else if (stmpNamingType.Equals("Overwrite", StringComparison.CurrentCultureIgnoreCase))
- {
tmpNamingType = NamingType.Overwrite;
- }
else
{
- m_log.Warn("Unknown naming type specified for region " + sRegionLabel + ": " +
- stmpNamingType);
+ m_log.Warn("Unknown naming type specified for Default");
tmpNamingType = NamingType.Time;
}
+ m_defaultState.NamingType = tmpNamingType;
- if (state == null && tmpNamingType != this.m_defaultState.NamingType)
- {
- state = new AutoBackupModuleState();
- }
+ m_defaultState.Script = config.GetString("AutoBackupScript", m_defaultState.Script);
- if (state != null)
- {
- state.NamingType = tmpNamingType;
- }
+ }
- string tmpScript = ResolveString("AutoBackupScript",
- this.m_defaultState.Script, config, regionConfig);
- if (state == null && tmpScript != this.m_defaultState.Script)
- {
- state = new AutoBackupModuleState();
- }
+ ///
+ /// Set up internal state for a given scene. Fairly complex code.
+ /// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene.
+ ///
+ /// The scene to look at.
+ /// Whether this call is intended to figure out what we consider the "default" config (applied to all regions unless overridden by per-region settings).
+ /// An AutoBackupModuleState contains most information you should need to know relevant to auto-backup, as applicable to a single region.
+ private AutoBackupModuleState ParseConfig(IScene scene)
+ {
+ if(scene == null)
+ return null;
- if (state != null)
- {
- state.Script = tmpScript;
- }
+ string sRegionName;
+ AutoBackupModuleState state = null;
- string tmpBackupDir = ResolveString("AutoBackupDir", ".", config, regionConfig);
- if (state == null && tmpBackupDir != this.m_defaultState.BackupDir)
- {
- state = new AutoBackupModuleState();
- }
+ sRegionName = scene.RegionInfo.RegionName;
- if (state != null)
- {
- state.BackupDir = tmpBackupDir;
- // Let's give the user some convenience and auto-mkdir
- if (state.BackupDir != ".")
- {
- try
- {
- DirectoryInfo dirinfo = new DirectoryInfo(state.BackupDir);
- if (!dirinfo.Exists)
- {
- dirinfo.Create();
- }
- }
- catch (Exception e)
- {
- m_log.Warn(
- "[AUTO BACKUP]: BAD NEWS. You won't be able to save backups to directory " +
- state.BackupDir +
- " because it doesn't exist or there's a permissions issue with it. Here's the exception.",
- e);
- }
- }
- }
+ // Read the config settings and set variables.
+ IConfig regionConfig = scene.Config.Configs[sRegionName];
+ if (regionConfig == null)
+ return null;
- if(state == null)
- return m_defaultState;
+ state = new AutoBackupModuleState();
- return state;
- }
+ state.Enabled = regionConfig.GetBoolean("AutoBackup", m_defaultState.Enabled);
- ///
- /// Helper function for ParseConfig.
- ///
- ///
- ///
- ///
- ///
- ///
- private bool ResolveBoolean(string settingName, bool defaultValue, IConfig global, IConfig local)
- {
- if(local != null)
- {
- return local.GetBoolean(settingName, global.GetBoolean(settingName, defaultValue));
- }
- else
- {
- return global.GetBoolean(settingName, defaultValue);
- }
- }
+ // Included Option To Skip Assets
+ state.SkipAssets = regionConfig.GetBoolean("AutoBackupSkipAssets", m_defaultState.SkipAssets);
- ///
- /// Helper function for ParseConfig.
- ///
- ///
- ///
- ///
- ///
- ///
- private double ResolveDouble(string settingName, double defaultValue, IConfig global, IConfig local)
- {
- if (local != null)
- {
- return local.GetDouble(settingName, global.GetDouble(settingName, defaultValue));
- }
+ // Set file naming algorithm
+ string stmpNamingType = regionConfig.GetString("AutoBackupNaming", m_defaultState.NamingType.ToString());
+ NamingType tmpNamingType;
+ if (stmpNamingType.Equals("Time", StringComparison.CurrentCultureIgnoreCase))
+ tmpNamingType = NamingType.Time;
+ else if (stmpNamingType.Equals("Sequential", StringComparison.CurrentCultureIgnoreCase))
+ tmpNamingType = NamingType.Sequential;
+ else if (stmpNamingType.Equals("Overwrite", StringComparison.CurrentCultureIgnoreCase))
+ tmpNamingType = NamingType.Overwrite;
else
{
- return global.GetDouble(settingName, defaultValue);
+ m_log.Warn("Unknown naming type specified for region " + sRegionName + ": " +
+ stmpNamingType);
+ tmpNamingType = NamingType.Time;
}
- }
+ m_defaultState.NamingType = tmpNamingType;
- ///
- /// Helper function for ParseConfig.
- ///
- ///
- ///
- ///
- ///
- ///
- private int ResolveInt(string settingName, int defaultValue, IConfig global, IConfig local)
- {
- if (local != null)
- {
- return local.GetInt(settingName, global.GetInt(settingName, defaultValue));
- }
- else
- {
- return global.GetInt(settingName, defaultValue);
- }
+ state.Script = regionConfig.GetString("AutoBackupScript", m_defaultState.Script);
+ return state;
}
- ///
- /// Helper function for ParseConfig.
- ///
- ///
- ///
- ///
- ///
- ///
- private string ResolveString(string settingName, string defaultValue, IConfig global, IConfig local)
- {
- if (local != null)
- {
- return local.GetString(settingName, global.GetString(settingName, defaultValue));
- }
- else
- {
- return global.GetString(settingName, defaultValue);
- }
- }
///
/// Called when any auto-backup timer expires. This starts the code path for actually performing a backup.
@@ -650,63 +442,27 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
///
private void HandleElapsed(object sender, ElapsedEventArgs e)
{
- // TODO: heuristic thresholds are per-region, so we should probably run heuristics once per region
- // XXX: Running heuristics once per region could add undue performance penalty for something that's supposed to
- // check whether the region is too busy! Especially on sims with LOTS of regions.
- // Alternative: make heuristics thresholds global to the module rather than per-region. Less flexible,
- // but would allow us to be semantically correct while being easier on perf.
- // Alternative 2: Run heuristics once per unique set of heuristics threshold parameters! Ay yi yi...
- // Alternative 3: Don't support per-region heuristics at all; just accept them as a global only parameter.
- // Since this is pretty experimental, I haven't decided which alternative makes the most sense.
- if (this.m_closed)
- {
+ if (!m_enabled || m_busy)
return;
- }
- bool heuristicsRun = false;
- bool heuristicsPassed = false;
- if (!this.m_timerMap.ContainsKey((Timer) sender))
+
+ m_busy = true;
+ if(m_doneFirst && m_KeepFilesForDays > 0)
+ RemoveOldFiles();
+
+ foreach (IScene scene in m_Scenes)
{
- m_log.Debug("[AUTO BACKUP]: Code-up error: timerMap doesn't contain timer " + sender);
+ if (!m_enabled)
+ return;
+ DoRegionBackup(scene);
}
- List tmap = this.m_timerMap[(Timer) sender];
- if (tmap != null && tmap.Count > 0)
+ if (m_enabled)
{
- foreach (IScene scene in tmap)
- {
- AutoBackupModuleState state = this.m_states[scene];
- bool heuristics = state.BusyCheck;
-
- // Fast path: heuristics are on; already ran em; and sim is fine; OR, no heuristics for the region.
- if ((heuristics && heuristicsRun && heuristicsPassed) || !heuristics)
- {
- this.DoRegionBackup(scene);
- // Heuristics are on; ran but we're too busy -- keep going. Maybe another region will have heuristics off!
- }
- else if (heuristicsRun)
- {
- m_log.Info("[AUTO BACKUP]: Heuristics: too busy to backup " +
- scene.RegionInfo.RegionName + " right now.");
- continue;
- // Logical Deduction: heuristics are on but haven't been run
- }
- else
- {
- heuristicsPassed = this.RunHeuristics(scene);
- heuristicsRun = true;
- if (!heuristicsPassed)
- {
- m_log.Info("[AUTO BACKUP]: Heuristics: too busy to backup " +
- scene.RegionInfo.RegionName + " right now.");
- continue;
- }
- this.DoRegionBackup(scene);
- }
-
- // Remove Old Backups
- this.RemoveOldFiles(state);
- }
+ m_masterTimer.Start();
+ m_busy = false;
}
+
+ m_doneFirst = true;
}
///
@@ -723,21 +479,29 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
return;
}
- AutoBackupModuleState state = this.m_states[scene];
+ m_busy = true;
+
+ AutoBackupModuleState state;
+ if(!m_states.TryGetValue(scene, out state))
+ return;
+
+ if(state == null || !state.Enabled)
+ return;
+
IRegionArchiverModule iram = scene.RequestModuleInterface();
+ if(iram == null)
+ return;
+
string savePath = BuildOarPath(scene.RegionInfo.RegionName,
- state.BackupDir,
+ m_backupDir,
state.NamingType);
if (savePath == null)
{
m_log.Warn("[AUTO BACKUP]: savePath is null in HandleElapsed");
return;
}
- Guid guid = Guid.NewGuid();
- m_pendingSaves.Add(guid, scene);
- state.LiveRequests.Add(guid, savePath);
- ((Scene) scene).EventManager.OnOarFileSaved += new EventManager.OarFileSaved(EventManager_OnOarFileSaved);
+ Guid guid = Guid.NewGuid();
m_log.Info("[AUTO BACKUP]: Backing up region " + scene.RegionInfo.RegionName);
// Must pass options, even if dictionary is empty!
@@ -747,47 +511,37 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
options["noassets"] = true;
iram.ArchiveRegion(savePath, guid, options);
+ ExecuteScript(state.Script, savePath);
}
// For the given state, remove backup files older than the states KeepFilesForDays property
- private void RemoveOldFiles(AutoBackupModuleState state)
+ private void RemoveOldFiles()
{
- // 0 Means Disabled, Keep Files Indefinitely
- if (state.KeepFilesForDays > 0)
+ string[] files;
+ try
{
- string[] files = Directory.GetFiles(state.BackupDir, "*.oar");
- DateTime CuttOffDate = DateTime.Now.AddDays(0 - state.KeepFilesForDays);
-
- foreach (string file in files)
- {
- try
- {
- FileInfo fi = new FileInfo(file);
- if (fi.CreationTime < CuttOffDate)
- fi.Delete();
- }
- catch (Exception Ex)
- {
- m_log.Error("[AUTO BACKUP]: Error deleting old backup file '" + file + "': " + Ex.Message);
- }
- }
+ files = Directory.GetFiles(m_backupDir, "*.oar");
+ }
+ catch (Exception Ex)
+ {
+ m_log.Error("[AUTO BACKUP]: Error reading backup folder " + m_backupDir + ": " + Ex.Message);
+ return;
}
- }
- ///
- /// Called by the Event Manager when the OnOarFileSaved event is fired.
- ///
- ///
- ///
- void EventManager_OnOarFileSaved(Guid guid, string message)
- {
- // Ignore if the OAR save is being done by some other part of the system
- if (m_pendingSaves.ContainsKey(guid))
+ DateTime CuttOffDate = DateTime.Now.AddDays(-m_KeepFilesForDays);
+
+ foreach (string file in files)
{
- AutoBackupModuleState abms = m_states[(m_pendingSaves[guid])];
- ExecuteScript(abms.Script, abms.LiveRequests[guid]);
- m_pendingSaves.Remove(guid);
- abms.LiveRequests.Remove(guid);
+ try
+ {
+ FileInfo fi = new FileInfo(file);
+ if (fi.CreationTime < CuttOffDate)
+ fi.Delete();
+ }
+ catch (Exception Ex)
+ {
+ m_log.Error("[AUTO BACKUP]: Error deleting old backup file '" + file + "': " + Ex.Message);
+ }
}
}
@@ -817,63 +571,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
return output;
}
- /// Return value of true ==> not too busy; false ==> too busy to backup an OAR right now, or error.
- private bool RunHeuristics(IScene region)
- {
- try
- {
- return this.RunTimeDilationHeuristic(region) && this.RunAgentLimitHeuristic(region);
- }
- catch (Exception e)
- {
- m_log.Warn("[AUTO BACKUP]: Exception in RunHeuristics", e);
- return false;
- }
- }
-
- ///
- /// If the time dilation right at this instant is less than the threshold specified in AutoBackupDilationThreshold (default 0.5),
- /// then we return false and trip the busy heuristic's "too busy" path (i.e. don't save an OAR).
- /// AutoBackupDilationThreshold is a _LOWER BOUND_. Lower Time Dilation is bad, so if you go lower than our threshold, it's "too busy".
- ///
- ///
- /// Returns true if we're not too busy; false means we've got worse time dilation than the threshold.
- private bool RunTimeDilationHeuristic(IScene region)
- {
- string regionName = region.RegionInfo.RegionName;
- return region.TimeDilation >=
- this.m_configSource.Configs["AutoBackupModule"].GetFloat(
- regionName + ".AutoBackupDilationThreshold", 0.5f);
- }
-
- ///
- /// If the root agent count right at this instant is less than the threshold specified in AutoBackupAgentThreshold (default 10),
- /// then we return false and trip the busy heuristic's "too busy" path (i.e., don't save an OAR).
- /// AutoBackupAgentThreshold is an _UPPER BOUND_. Higher Agent Count is bad, so if you go higher than our threshold, it's "too busy".
- ///
- ///
- /// Returns true if we're not too busy; false means we've got more agents on the sim than the threshold.
- private bool RunAgentLimitHeuristic(IScene region)
- {
- string regionName = region.RegionInfo.RegionName;
- try
- {
- Scene scene = (Scene) region;
- // TODO: Why isn't GetRootAgentCount() a method in the IScene interface? Seems generally useful...
- return scene.GetRootAgentCount() <=
- this.m_configSource.Configs["AutoBackupModule"].GetInt(
- regionName + ".AutoBackupAgentThreshold", 10);
- }
- catch (InvalidCastException ice)
- {
- m_log.Debug(
- "[AUTO BACKUP]: I NEED MAINTENANCE: IScene is not a Scene; can't get root agent count!",
- ice);
- return true;
- // Non-obstructionist safest answer...
- }
- }
-
///
/// Run the script or executable specified by the "AutoBackupScript" config setting.
/// Of course this is a security risk if you let anyone modify OpenSim.ini and they want to run some nasty bash script.
@@ -920,18 +617,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
}
///
- /// Quickly stop all timers from firing.
- ///
- private void StopAllTimers()
- {
- foreach (Timer t in this.m_timerMap.Keys)
- {
- t.Close();
- }
- this.m_closed = true;
- }
-
- ///
/// Determine the next unique filename by number, for "Sequential" AutoBackupNamingType.
///
///
@@ -1033,5 +718,3 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
}
}
}
-
-
diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs
index ce7c368..fb87677 100644
--- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs
+++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs
@@ -35,29 +35,23 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// If you use this class in any way outside of AutoBackupModule, you should treat the class as opaque.
/// Since it is not part of the framework, you really should not rely upon it outside of the AutoBackupModule implementation.
///
- ///
+ ///
public class AutoBackupModuleState
{
- private Dictionary m_liveRequests = null;
-
public AutoBackupModuleState()
{
- this.Enabled = false;
- this.BackupDir = ".";
- this.BusyCheck = true;
- this.SkipAssets = false;
- this.Timer = null;
- this.NamingType = NamingType.Time;
- this.Script = null;
- this.KeepFilesForDays = 0;
+ Enabled = false;
+ SkipAssets = false;
+ NamingType = NamingType.Time;
+ Script = null;
}
- public Dictionary LiveRequests
+ public AutoBackupModuleState(AutoBackupModuleState copyFrom)
{
- get {
- return this.m_liveRequests ??
- (this.m_liveRequests = new Dictionary(1));
- }
+ Enabled = copyFrom.Enabled;
+ SkipAssets = copyFrom.SkipAssets;
+ NamingType = copyFrom.NamingType;
+ Script = copyFrom.Script;
}
public bool Enabled
@@ -66,33 +60,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
set;
}
- public System.Timers.Timer Timer
- {
- get;
- set;
- }
-
- public double IntervalMinutes
- {
- get
- {
- if (this.Timer == null)
- {
- return -1.0;
- }
- else
- {
- return this.Timer.Interval / 60000.0;
- }
- }
- }
-
- public bool BusyCheck
- {
- get;
- set;
- }
-
public bool SkipAssets
{
get;
@@ -105,36 +72,19 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
set;
}
- public string BackupDir
- {
- get;
- set;
- }
-
public NamingType NamingType
{
get;
set;
}
- public int KeepFilesForDays
- {
- get;
- set;
- }
-
public new string ToString()
{
string retval = "";
-
retval += "[AUTO BACKUP]: AutoBackup: " + (Enabled ? "ENABLED" : "DISABLED") + "\n";
- retval += "[AUTO BACKUP]: Interval: " + IntervalMinutes + " minutes" + "\n";
- retval += "[AUTO BACKUP]: Do Busy Check: " + (BusyCheck ? "Yes" : "No") + "\n";
retval += "[AUTO BACKUP]: Naming Type: " + NamingType.ToString() + "\n";
- retval += "[AUTO BACKUP]: Backup Dir: " + BackupDir + "\n";
retval += "[AUTO BACKUP]: Script: " + Script + "\n";
return retval;
}
}
}
-
diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
index 5f47810..b32a429 100644
--- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
+++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
@@ -65,10 +65,10 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
///
// private UUID EconomyBaseAccount = UUID.Zero;
- private float EnergyEfficiency = 0f;
+ private float EnergyEfficiency = 1f;
// private ObjectPaid handerOnObjectPaid;
private bool m_enabled = true;
- private bool m_sellEnabled = false;
+ private bool m_sellEnabled = true;
private IConfigSource m_gConfig;
@@ -85,12 +85,12 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
private int ObjectCount = 0;
private int PriceEnergyUnit = 0;
- private int PriceGroupCreate = 0;
+ private int PriceGroupCreate = -1;
private int PriceObjectClaim = 0;
private float PriceObjectRent = 0f;
- private float PriceObjectScaleFactor = 0f;
+ private float PriceObjectScaleFactor = 10f;
private int PriceParcelClaim = 0;
- private float PriceParcelClaimFactor = 0f;
+ private float PriceParcelClaimFactor = 1f;
private int PriceParcelRent = 0;
private int PricePublicObjectDecay = 0;
private int PricePublicObjectDelete = 0;
@@ -98,7 +98,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
private int PriceUpload = 0;
private int TeleportMinPrice = 0;
- private float TeleportPriceExponent = 0f;
+ private float TeleportPriceExponent = 2f;
#region IMoneyModule Members
@@ -124,13 +124,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
public void Initialise(IConfigSource config)
{
m_gConfig = config;
-
- IConfig startupConfig = m_gConfig.Configs["Startup"];
- IConfig economyConfig = m_gConfig.Configs["Economy"];
-
-
- ReadConfigAndPopulate(startupConfig, "Startup");
- ReadConfigAndPopulate(economyConfig, "Economy");
+ ReadConfigAndPopulate();
}
public void AddRegion(Scene scene)
@@ -151,13 +145,13 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
// to the command line parameters you use to start up your client
// This commonly looks like -helperuri http://127.0.0.1:9000/
-
+
// Local Server.. enables functionality only.
httpServer.AddXmlRPCHandler("getCurrencyQuote", quote_func);
httpServer.AddXmlRPCHandler("buyCurrency", buy_func);
httpServer.AddXmlRPCHandler("preflightBuyLandPrep", preflightBuyLandPrep_func);
httpServer.AddXmlRPCHandler("buyLandPrep", landBuy_func);
-
+
}
if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle))
@@ -205,13 +199,14 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
{
}
- public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount)
+ public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount, UUID txn, out string result)
{
+ result = String.Empty;
string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID));
bool give_result = doMoneyTransfer(fromID, toID, amount, 2, description);
-
+
BalanceUpdate(fromID, toID, give_result, description);
return give_result;
@@ -240,35 +235,51 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
///
/// Parse Configuration
///
- ///
- ///
- ///
- private void ReadConfigAndPopulate(IConfig startupConfig, string config)
+ private void ReadConfigAndPopulate()
{
- if (config == "Startup" && startupConfig != null)
+ // we are enabled by default
+
+ IConfig startupConfig = m_gConfig.Configs["Startup"];
+
+ if(startupConfig == null) // should not happen
+ return;
+
+ IConfig economyConfig = m_gConfig.Configs["Economy"];
+
+ // economymodule may be at startup or Economy (legacy)
+ string mmodule = startupConfig.GetString("economymodule","");
+ if(String.IsNullOrEmpty(mmodule))
{
- m_enabled = (startupConfig.GetString("economymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule");
+ if(economyConfig != null)
+ mmodule = economyConfig.GetString("economymodule","");
}
- if (config == "Economy" && startupConfig != null)
+ if(!String.IsNullOrEmpty(mmodule) && mmodule != Name)
{
- PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100);
- PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10);
- PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4);
- PricePublicObjectDelete = startupConfig.GetInt("PricePublicObjectDelete", 4);
- PriceParcelClaim = startupConfig.GetInt("PriceParcelClaim", 1);
- PriceParcelClaimFactor = startupConfig.GetFloat("PriceParcelClaimFactor", 1f);
- PriceUpload = startupConfig.GetInt("PriceUpload", 0);
- PriceRentLight = startupConfig.GetInt("PriceRentLight", 5);
- TeleportMinPrice = startupConfig.GetInt("TeleportMinPrice", 2);
- TeleportPriceExponent = startupConfig.GetFloat("TeleportPriceExponent", 2f);
- EnergyEfficiency = startupConfig.GetFloat("EnergyEfficiency", 1);
- PriceObjectRent = startupConfig.GetFloat("PriceObjectRent", 1);
- PriceObjectScaleFactor = startupConfig.GetFloat("PriceObjectScaleFactor", 10);
- PriceParcelRent = startupConfig.GetInt("PriceParcelRent", 1);
- PriceGroupCreate = startupConfig.GetInt("PriceGroupCreate", -1);
- m_sellEnabled = startupConfig.GetBoolean("SellEnabled", false);
+ // some other money module selected
+ m_enabled = false;
+ return;
}
+
+ if(economyConfig == null)
+ return;
+
+ PriceEnergyUnit = economyConfig.GetInt("PriceEnergyUnit", 0);
+ PriceObjectClaim = economyConfig.GetInt("PriceObjectClaim", 0);
+ PricePublicObjectDecay = economyConfig.GetInt("PricePublicObjectDecay", 4);
+ PricePublicObjectDelete = economyConfig.GetInt("PricePublicObjectDelete", 0);
+ PriceParcelClaim = economyConfig.GetInt("PriceParcelClaim", 0);
+ PriceParcelClaimFactor = economyConfig.GetFloat("PriceParcelClaimFactor", 1f);
+ PriceUpload = economyConfig.GetInt("PriceUpload", 0);
+ PriceRentLight = economyConfig.GetInt("PriceRentLight", 0);
+ TeleportMinPrice = economyConfig.GetInt("TeleportMinPrice", 0);
+ TeleportPriceExponent = economyConfig.GetFloat("TeleportPriceExponent", 2f);
+ EnergyEfficiency = economyConfig.GetFloat("EnergyEfficiency", 1);
+ PriceObjectRent = economyConfig.GetFloat("PriceObjectRent", 0);
+ PriceObjectScaleFactor = economyConfig.GetFloat("PriceObjectScaleFactor", 10);
+ PriceParcelRent = economyConfig.GetInt("PriceParcelRent", 0);
+ PriceGroupCreate = economyConfig.GetInt("PriceGroupCreate", -1);
+ m_sellEnabled = economyConfig.GetBoolean("SellEnabled", true);
}
private void GetClientFunds(IClientAPI client)
@@ -302,7 +313,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
private bool doMoneyTransfer(UUID Sender, UUID Receiver, int amount, int transactiontype, string description)
{
bool result = true;
-
+
return result;
}
@@ -376,10 +387,10 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
else
{
m_log.ErrorFormat(
- "[MONEY]: Could not resolve user {0}",
+ "[MONEY]: Could not resolve user {0}",
agentID);
}
-
+
return String.Empty;
}
@@ -463,7 +474,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
Hashtable quoteResponse = new Hashtable();
XmlRpcResponse returnval = new XmlRpcResponse();
-
+
Hashtable currencyResponse = new Hashtable();
currencyResponse.Add("estimatedCost", 0);
currencyResponse.Add("currencyBuy", amount);
@@ -474,7 +485,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
returnval.Value = quoteResponse;
return returnval;
-
+
}
@@ -484,7 +495,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
// Hashtable requestData = (Hashtable) request.Params[0];
// UUID agentId = UUID.Zero;
// int amount = 0;
-
+
XmlRpcResponse returnval = new XmlRpcResponse();
Hashtable returnresp = new Hashtable();
returnresp.Add("success", true);
@@ -535,7 +546,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
// UUID agentId = UUID.Zero;
// int amount = 0;
-
+
retparam.Add("success", true);
ret.Value = retparam;
@@ -552,7 +563,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
///
private void CheckExistAndRefreshFunds(UUID agentID)
{
-
+
}
///
@@ -562,14 +573,14 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
///
private int GetFundsForAgentID(UUID AgentID)
{
- int returnfunds = 82101; // Set it to the OpenSim version, plus the IG build number. Muahahaha;
-
+ int returnfunds = 0;
+
return returnfunds;
}
// private void SetLocalFundsForAgentID(UUID AgentID, int amount)
// {
-
+
// }
#endregion
@@ -688,7 +699,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
///
public void ClientClosed(UUID AgentID, Scene scene)
{
-
+
}
///
@@ -707,19 +718,19 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
private void ValidateLandBuy(Object osender, EventManager.LandBuyArgs e)
{
-
-
+
+
lock (e)
{
e.economyValidated = true;
}
-
-
+
+
}
private void processLandBuy(Object osender, EventManager.LandBuyArgs e)
{
-
+
}
///
@@ -729,7 +740,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
///
private void MoneyTransferAction(Object osender, EventManager.MoneyTransferArgs e)
{
-
+
}
///
@@ -738,7 +749,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
///
private void MakeChildAgent(ScenePresence avatar)
{
-
+
}
///
@@ -747,7 +758,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
///
private void ClientLoggedOut(UUID AgentId, Scene scene)
{
-
+
}
///
@@ -767,7 +778,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
///
private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID)
{
-
+
//m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString());
}
@@ -808,12 +819,12 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
Scene s = LocateSceneClientIn(remoteClient.AgentId);
- // Implmenting base sale data checking here so the default OpenSimulator implementation isn't useless
+ // Implmenting base sale data checking here so the default OpenSimulator implementation isn't useless
// combined with other implementations. We're actually validating that the client is sending the data
// that it should. In theory, the client should already know what to send here because it'll see it when it
- // gets the object data. If the data sent by the client doesn't match the object, the viewer probably has an
- // old idea of what the object properties are. Viewer developer Hazim informed us that the base module
- // didn't check the client sent data against the object do any. Since the base modules are the
+ // gets the object data. If the data sent by the client doesn't match the object, the viewer probably has an
+ // old idea of what the object properties are. Viewer developer Hazim informed us that the base module
+ // didn't check the client sent data against the object do any. Since the base modules are the
// 'crowning glory' examples of good practice..
// Validate that the object exists in the scene the user is in
@@ -823,15 +834,15 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
remoteClient.SendAgentAlertMessage("Unable to buy now. The object was not found.", false);
return;
}
-
- // Validate that the client sent the price that the object is being sold for
+
+ // Validate that the client sent the price that the object is being sold for
if (part.SalePrice != salePrice)
{
remoteClient.SendAgentAlertMessage("Cannot buy at this price. Buy Failed. If you continue to get this relog.", false);
return;
}
- // Validate that the client sent the proper sale type the object has set
+ // Validate that the client sent the proper sale type the object has set
if (part.ObjectSaleType != saleType)
{
remoteClient.SendAgentAlertMessage("Cannot buy this way. Buy Failed. If you continue to get this relog.", false);
@@ -842,6 +853,15 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
if (module != null)
module.BuyObject(remoteClient, categoryID, localID, saleType, salePrice);
}
+
+ public void MoveMoney(UUID fromUser, UUID toUser, int amount, string text)
+ {
+ }
+
+ public bool MoveMoney(UUID fromUser, UUID toUser, int amount, MoneyTransactionType type, string text)
+ {
+ return true;
+ }
}
public enum TransactionType : int
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index fb644b7..bb23f2f 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -43,9 +43,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public class NPCAvatar : IClientAPI, INPC
{
public bool SenseAsAgent { get; set; }
+ public UUID Owner
+ {
+ get { return m_ownerID;}
+ }
public delegate void ChatToNPC(
- string message, byte type, Vector3 fromPos, string fromName,
+ string message, byte type, Vector3 fromPos, string fromName,
UUID fromAgentID, UUID ownerID, byte source, byte audible);
///
@@ -61,9 +65,14 @@ namespace OpenSim.Region.OptionalModules.World.NPC
private readonly string m_firstname;
private readonly string m_lastname;
private readonly Vector3 m_startPos;
- private readonly UUID m_uuid;
+ private UUID m_uuid = UUID.Random();
private readonly Scene m_scene;
private readonly UUID m_ownerID;
+ private UUID m_hostGroupID;
+ private string m_profileAbout = "";
+ private UUID m_profileImage = UUID.Zero;
+ private string m_born;
+ public List SelectedObjects {get; private set;}
public NPCAvatar(
string firstname, string lastname, Vector3 position, UUID ownerID, bool senseAsAgent, Scene scene)
@@ -75,6 +84,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
m_scene = scene;
m_ownerID = ownerID;
SenseAsAgent = senseAsAgent;
+ m_hostGroupID = UUID.Zero;
}
public NPCAvatar(
@@ -87,6 +97,25 @@ namespace OpenSim.Region.OptionalModules.World.NPC
m_scene = scene;
m_ownerID = ownerID;
SenseAsAgent = senseAsAgent;
+ m_hostGroupID = UUID.Zero;
+ }
+
+ public string profileAbout
+ {
+ get { return m_profileAbout; }
+ set
+ {
+ if(value.Length > 255)
+ m_profileAbout = value.Substring(0,255);
+ else
+ m_profileAbout = value;
+ }
+ }
+
+ public UUID profileImage
+ {
+ get { return m_profileImage; }
+ set { m_profileImage = value; }
}
public IScene Scene
@@ -94,6 +123,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
get { return m_scene; }
}
+ public int PingTimeMS { get { return 0; } }
+
public UUID OwnerID
{
get { return m_ownerID; }
@@ -187,9 +218,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
-
- public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot,
- Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
+
+ public void SendFindAgent(UUID HunterID, UUID PreyID, double GlobalX, double GlobalY)
+ {
+
+ }
+
+ public void SendSitResponse(UUID TargetID, Vector3 OffsetPos,
+ Quaternion SitOrientation, bool autopilot,
+ Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
{
}
@@ -248,7 +285,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
#pragma warning disable 67
public event Action OnLogout;
public event ObjectPermissions OnObjectPermissions;
-
+ public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
public event MoneyTransferRequest OnMoneyTransferRequest;
public event ParcelBuy OnParcelBuy;
public event Action OnConnectionClosed;
@@ -268,6 +305,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public event ObjectDrop OnObjectDrop;
public event StartAnim OnStartAnim;
public event StopAnim OnStopAnim;
+ public event ChangeAnim OnChangeAnim;
public event LinkObjects OnLinkObjects;
public event DelinkObjects OnDelinkObjects;
public event RequestMapBlocks OnRequestMapBlocks;
@@ -280,6 +318,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public event SetAlwaysRun OnSetAlwaysRun;
public event DeRezObject OnDeRezObject;
+ public event RezRestoreToWorld OnRezRestoreToWorld;
public event Action OnRegionHandShakeReply;
public event GenericCall1 OnRequestWearables;
public event Action OnCompleteMovementToRegion;
@@ -318,6 +357,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public event UpdatePrimTexture OnUpdatePrimTexture;
public event UpdateVector OnUpdatePrimGroupPosition;
public event UpdateVector OnUpdatePrimSinglePosition;
+ public event ClientChangeObject onClientChangeObject;
public event UpdatePrimRotation OnUpdatePrimGroupRotation;
public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition;
public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
@@ -456,7 +496,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public event ClassifiedInfoRequest OnClassifiedInfoRequest;
public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
public event ClassifiedDelete OnClassifiedDelete;
- public event ClassifiedDelete OnClassifiedGodDelete;
+ public event ClassifiedGodDelete OnClassifiedGodDelete;
public event EventNotificationAddRequest OnEventNotificationAddRequest;
public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
@@ -479,7 +519,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public event AvatarInterestUpdate OnAvatarInterestUpdate;
public event PlacesQuery OnPlacesQuery;
-
+
public event FindAgentUpdate OnFindAgent;
public event TrackAgentUpdate OnTrackAgent;
public event NewUserReport OnUserReport;
@@ -495,11 +535,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
public event SimWideDeletesDelegate OnSimWideDeletes;
public event SendPostcard OnSendPostcard;
+ public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
public event MuteListEntryUpdate OnUpdateMuteListEntry;
public event MuteListEntryRemove OnRemoveMuteListEntry;
public event GodlikeMessage onGodlikeMessage;
public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
-
+ public event GenericCall2 OnUpdateThrottles;
#pragma warning restore 67
#endregion
@@ -522,6 +563,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public virtual UUID AgentId
{
get { return m_uuid; }
+ set { m_uuid = value; }
}
public UUID SessionId
@@ -562,24 +604,40 @@ namespace OpenSim.Region.OptionalModules.World.NPC
}
public UUID ActiveGroupId
{
- get { return UUID.Zero; }
+ get { return m_hostGroupID; }
+ set { m_hostGroupID = value; }
}
public string ActiveGroupName
{
get { return String.Empty; }
+ set { }
}
public ulong ActiveGroupPowers
{
get { return 0; }
+ set { }
+ }
+
+ public string Born
+ {
+ get { return m_born; }
+ set { m_born = value; }
}
public bool IsGroupMember(UUID groupID)
{
- return false;
+ return (m_hostGroupID == groupID);
+ }
+
+ public Dictionary GetGroupPowers()
+ {
+ return new Dictionary();
}
+ public void SetGroupPowers(Dictionary powers) { }
+
public ulong GetGroupPowers(UUID groupID)
{
return 0;
@@ -627,6 +685,17 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public virtual void SetChildAgentThrottle(byte[] throttle)
{
}
+
+ public virtual void SetChildAgentThrottle(byte[] throttle, float factor)
+ {
+
+ }
+
+ public void SetAgentThrottleSilent(int throttle, int setting)
+ {
+
+
+ }
public byte[] GetThrottlesPacked(float multiplier)
{
return new byte[0];
@@ -665,6 +734,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
}
+ public virtual bool CanSendLayerData()
+ {
+ return false;
+ }
+
public virtual void SendLayerData(float[] map)
{
}
@@ -676,9 +750,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
- public virtual void SendWindData(Vector2[] windSpeeds) { }
+ public virtual void SendWindData(int version, Vector2[] windSpeeds) { }
- public virtual void SendCloudData(float[] cloudCover) { }
+ public virtual void SendCloudData(int version, float[] cloudCover) { }
public virtual void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
{
@@ -739,7 +813,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
- public void SendAvatarDataImmediate(ISceneEntity avatar)
+ public void SendEntityFullUpdateImmediate(ISceneEntity avatar)
+ {
+ }
+
+ public void SendEntityTerseUpdateImmediate(ISceneEntity ent)
{
}
@@ -772,6 +850,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
+ public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
+ {
+ }
+
public virtual void SendRemoveInventoryItem(UUID itemID)
{
}
@@ -788,7 +870,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
- public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data)
+ public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
{
}
public virtual void SendAbortXferPacket(ulong xferID)
@@ -833,6 +915,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
+ public void SendAlertMessage(string message, string info)
+ {
+ }
+
public void SendSystemAlertMessage(string message)
{
}
@@ -849,7 +935,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
OnRegionHandShakeReply(this);
}
}
-
+
public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
{
}
@@ -869,7 +955,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public void SendImageFirstPart(ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec)
{
}
-
+
public void SendImageNotFound(UUID imageid)
{
}
@@ -877,7 +963,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData)
{
}
-
+
public void SendShutdownConnectionNotice()
{
}
@@ -888,7 +974,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public void SendObjectPropertiesFamilyData(ISceneEntity Entity, uint RequestFlags)
{
-
+
}
public void SendObjectPropertiesReply(ISceneEntity entity)
@@ -902,12 +988,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks)
{
}
-
+
public void SendViewerTime(int phase)
{
}
- public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember,
+ public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] membershipType,
string flAbout, uint flags, UUID flImageID, UUID imageID, string profileURL,
UUID partnerID)
{
@@ -933,10 +1019,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public void Close()
{
- Close(false);
+ Close(true, false);
}
- public void Close(bool force)
+ public void Close(bool sendStop, bool force)
{
// Remove ourselves from the scene
m_scene.RemoveClient(AgentId, false);
@@ -947,7 +1033,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
// We never start the client, so always fail.
throw new NotImplementedException();
}
-
+
public void Stop()
{
}
@@ -1142,11 +1228,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public void SendJoinGroupReply(UUID groupID, bool success)
{
}
-
+
public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success)
{
}
-
+
public void SendLeaveGroupReply(UUID groupID, bool success)
{
}
@@ -1155,6 +1241,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
+ public void SendAgentGroupDataUpdate(UUID avatarID, GroupMembershipData[] data)
+ {
+ }
+
public void SendTerminateFriend(UUID exFriendID)
{
}
@@ -1208,10 +1298,26 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
+ public void UpdateGroupMembership(GroupMembershipData[] data)
+ {
+ }
+
+ public void GroupMembershipRemove(UUID GroupID)
+ {
+ }
+
+ public void GroupMembershipAddReplace(UUID GroupID,ulong GroupPowers)
+ {
+ }
+
public void SendUseCachedMuteList()
{
}
+ public void SendEmpytMuteList()
+ {
+ }
+
public void SendMuteListUpdate(string filename)
{
}
@@ -1220,7 +1326,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
#endregion
-
+
public void SendRebakeAvatarTextures(UUID textureID)
{
}
@@ -1228,15 +1334,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public void SendAvatarInterestsReply(UUID avatarID, uint wantMask, string wantText, uint skillsMask, string skillsText, string languages)
{
}
-
+
public void SendGroupAccountingDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID, int amt)
{
}
-
+
public void SendGroupAccountingSummary(IClientAPI sender,UUID groupID, uint moneyAmt, int totalTier, int usedTier)
{
}
-
+
public void SendGroupTransactionsSummaryDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID,int amt)
{
}
@@ -1256,7 +1362,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId)
{
}
-
+
public void SendAgentTerseUpdate(ISceneEntity presence)
{
}
@@ -1265,9 +1371,22 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
+ public void SendSelectedPartsProprieties(List parts)
+ {
+ }
+
public void SendPartPhysicsProprieties(ISceneEntity entity)
{
}
+ public void SendPartFullUpdate(ISceneEntity ent, uint? parentID)
+ {
+ }
+
+ public int GetAgentThrottleSilent(int throttle)
+ {
+ return 0;
+ }
+
}
}
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 3b94dff..ced82e6 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -52,6 +52,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
private Dictionary m_avatars =
new Dictionary();
+
+
+ private NPCOptionsFlags m_NPCOptionFlags;
+ public NPCOptionsFlags NPCOptionFlags {get {return m_NPCOptionFlags;}}
+
public bool Enabled { get; private set; }
public void Initialise(IConfigSource source)
@@ -59,6 +64,21 @@ namespace OpenSim.Region.OptionalModules.World.NPC
IConfig config = source.Configs["NPC"];
Enabled = (config != null && config.GetBoolean("Enabled", false));
+ m_NPCOptionFlags = NPCOptionsFlags.None;
+ if(Enabled)
+ {
+ if(config.GetBoolean("AllowNotOwned", true))
+ m_NPCOptionFlags |= NPCOptionsFlags.AllowNotOwned;
+
+ if(config.GetBoolean("AllowSenseAsAvatar", true))
+ m_NPCOptionFlags |= NPCOptionsFlags.AllowSenseAsAvatar;
+
+ if(config.GetBoolean("AllowCloneOtherAvatars", true))
+ m_NPCOptionFlags |= NPCOptionsFlags.AllowCloneOtherAvatars;
+
+ if(config.GetBoolean("NoNPCGroup", true))
+ m_NPCOptionFlags |= NPCOptionsFlags.NoNPCGroup;
+ }
}
public void AddRegion(Scene scene)
@@ -137,17 +157,18 @@ namespace OpenSim.Region.OptionalModules.World.NPC
}
public UUID CreateNPC(string firstname, string lastname,
- Vector3 position, UUID owner, bool senseAsAgent, Scene scene,
+ Vector3 position, UUID owner, bool senseAsAgent, Scene scene,
AvatarAppearance appearance)
{
- return CreateNPC(firstname, lastname, position, UUID.Zero, owner, senseAsAgent, scene, appearance);
+ return CreateNPC(firstname, lastname, position, UUID.Zero, owner, "", UUID.Zero, senseAsAgent, scene, appearance);
}
public UUID CreateNPC(string firstname, string lastname,
- Vector3 position, UUID agentID, UUID owner, bool senseAsAgent, Scene scene,
+ Vector3 position, UUID agentID, UUID owner, string groupTitle, UUID groupID, bool senseAsAgent, Scene scene,
AvatarAppearance appearance)
{
NPCAvatar npcAvatar = null;
+ string born = DateTime.UtcNow.ToString();
try
{
@@ -167,10 +188,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0,
int.MaxValue);
- m_log.DebugFormat(
- "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}",
- firstname, lastname, npcAvatar.AgentId, owner,
- senseAsAgent, position, scene.RegionInfo.RegionName);
+// m_log.DebugFormat(
+// "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}",
+// firstname, lastname, npcAvatar.AgentId, owner, senseAsAgent, position, scene.RegionInfo.RegionName);
AgentCircuitData acd = new AgentCircuitData();
acd.AgentID = npcAvatar.AgentId;
@@ -181,30 +201,44 @@ namespace OpenSim.Region.OptionalModules.World.NPC
AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true);
acd.Appearance = npcAppearance;
- lock (m_avatars)
+ /*
+ for (int i = 0;
+ i < acd.Appearance.Texture.FaceTextures.Length; i++)
{
- scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode,
- acd);
- scene.AddNewAgent(npcAvatar, PresenceType.Npc);
+ m_log.DebugFormat(
+ "[NPC MODULE]: NPC avatar {0} has texture id {1} : {2}",
+ acd.AgentID, i,
+ acd.Appearance.Texture.FaceTextures[i]);
+ }
+ */
- ScenePresence sp;
- if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
- {
- sp.CompleteMovement(npcAvatar, false);
- m_avatars.Add(npcAvatar.AgentId, npcAvatar);
- m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
+// ManualResetEvent ev = new ManualResetEvent(false);
- return npcAvatar.AgentId;
- }
- else
+// Util.FireAndForget(delegate(object x) {
+ lock (m_avatars)
{
- m_log.WarnFormat(
- "[NPC MODULE]: Could not find scene presence for NPC {0} {1}",
- sp.Name, sp.UUID);
+ scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
+ scene.AddNewAgent(npcAvatar, PresenceType.Npc);
- return UUID.Zero;
+ ScenePresence sp;
+ if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
+ {
+ npcAvatar.Born = born;
+ npcAvatar.ActiveGroupId = groupID;
+ sp.CompleteMovement(npcAvatar, false);
+ sp.Grouptitle = groupTitle;
+ m_avatars.Add(npcAvatar.AgentId, npcAvatar);
+// m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
+ }
}
- }
+// ev.Set();
+// });
+
+// ev.WaitOne();
+
+// m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", npcAvatar.AgentId);
+
+ return npcAvatar.AgentId;
}
public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos,
@@ -220,6 +254,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
if (sp.IsSatOnObject || sp.SitGround)
return false;
+// m_log.DebugFormat(
+// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
+// sp.Name, pos, scene.RegionInfo.RegionName,
+// noFly, landAtTarget);
+
sp.MoveToTarget(pos, noFly, landAtTarget);
sp.SetAlwaysRun = running;
@@ -382,6 +421,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
if (m_avatars.TryGetValue(agentID, out av))
{
+ /*
+ m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove",
+ agentID, av.Name);
+ */
doRemove = true;
}
}
@@ -410,9 +453,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
NPCAvatar av;
if (m_avatars.TryGetValue(npcID, out av))
+ {
+ if (npcID == callerID)
+ return true;
return CheckPermissions(av, callerID);
+ }
else
+ {
return false;
+ }
}
}
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 77dfd40..9a1ea73 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -112,7 +112,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
// ScenePresence.SendInitialData() to reset our entire appearance.
m_scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId));
- m_afMod.SetAppearance(sp, originalTe, null, null);
+ m_afMod.SetAppearance(sp, originalTe, null, new WearableCacheItem[0] );
UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance);
@@ -209,10 +209,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
UserAccountHelpers.CreateUserWithInventory(m_scene, userId);
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
- InventoryItemBase att1Item
+ InventoryItemBase att1Item
= UserInventoryHelpers.CreateInventoryItem(
m_scene, "att1", TestHelpers.ParseTail(0x2), TestHelpers.ParseTail(0x3), sp.UUID, InventoryType.Object);
- InventoryItemBase att2Item
+ InventoryItemBase att2Item
= UserInventoryHelpers.CreateInventoryItem(
m_scene, "att2", TestHelpers.ParseTail(0x12), TestHelpers.ParseTail(0x13), sp.UUID, InventoryType.Object);
@@ -483,4 +483,4 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
Assert.That(npc.ParentID, Is.EqualTo(0));
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
index 0927c4f..7e3bd7f 100644
--- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
@@ -54,38 +54,38 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
private Scene m_scene;
public string Name { get { return "Scene Commands Module"; } }
-
+
public Type ReplaceableInterface { get { return null; } }
-
+
public void Initialise(IConfigSource source)
{
// m_log.DebugFormat("[SCENE COMMANDS MODULE]: INITIALIZED MODULE");
}
-
+
public void PostInitialise()
{
// m_log.DebugFormat("[SCENE COMMANDS MODULE]: POST INITIALIZED MODULE");
}
-
+
public void Close()
{
// m_log.DebugFormat("[SCENE COMMANDS MODULE]: CLOSED MODULE");
}
-
+
public void AddRegion(Scene scene)
{
// m_log.DebugFormat("[SCENE COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
m_scene = scene;
-
+
m_scene.RegisterModuleInterface(this);
}
-
+
public void RemoveRegion(Scene scene)
{
// m_log.DebugFormat("[SCENE COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
- }
-
+ }
+
public void RegionLoaded(Scene scene)
{
// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
@@ -96,19 +96,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
"List current scene options.",
"active - if false then main scene update and maintenance loops are suspended.\n"
+ "animations - if true then extra animations debug information is logged.\n"
- + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n"
- + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n"
- + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
- + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
- + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n"
- + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n"
- + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n"
+ "collisions - if false then collisions with other objects are turned off.\n"
+ "pbackup - if false then periodic scene backup is turned off.\n"
+ "physics - if false then all physics objects are non-physical.\n"
+ "scripting - if false then no scripting operations happen.\n"
+ "teleport - if true then some extra teleport debug information is logged.\n"
- + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n"
+ "updates - if true then any frame which exceeds double the maximum desired frame time is logged.",
HandleDebugSceneGetCommand);
@@ -118,19 +110,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
"Turn on scene debugging options.",
"active - if false then main scene update and maintenance loops are suspended.\n"
+ "animations - if true then extra animations debug information is logged.\n"
- + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n"
- + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n"
- + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
- + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
- + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n"
- + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n"
- + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n"
+ "collisions - if false then collisions with other objects are turned off.\n"
+ "pbackup - if false then periodic scene backup is turned off.\n"
+ "physics - if false then all physics objects are non-physical.\n"
+ "scripting - if false then no scripting operations happen.\n"
+ "teleport - if true then some extra teleport debug information is logged.\n"
- + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n"
+ "updates - if true then any frame which exceeds double the maximum desired frame time is logged.",
HandleDebugSceneSetCommand);
}
@@ -155,18 +139,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
ConsoleDisplayList cdl = new ConsoleDisplayList();
cdl.AddRow("active", m_scene.Active);
cdl.AddRow("animations", m_scene.DebugAnimations);
- cdl.AddRow("appear-refresh", m_scene.SendPeriodicAppearanceUpdates);
- cdl.AddRow("child-repri", m_scene.ChildReprioritizationDistance);
- cdl.AddRow("client-pos-upd", m_scene.RootPositionUpdateTolerance);
- cdl.AddRow("client-rot-upd", m_scene.RootRotationUpdateTolerance);
- cdl.AddRow("client-vel-upd", m_scene.RootVelocityUpdateTolerance);
- cdl.AddRow("root-upd-per", m_scene.RootTerseUpdatePeriod);
- cdl.AddRow("child-upd-per", m_scene.ChildTerseUpdatePeriod);
cdl.AddRow("pbackup", m_scene.PeriodicBackup);
cdl.AddRow("physics", m_scene.PhysicsEnabled);
cdl.AddRow("scripting", m_scene.ScriptsEnabled);
cdl.AddRow("teleport", m_scene.DebugTeleporting);
- cdl.AddRow("update-on-timer", m_scene.UpdateOnTimer);
cdl.AddRow("updates", m_scene.DebugUpdates);
MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name);
@@ -210,69 +186,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
m_scene.DebugAnimations = active;
}
- if (options.ContainsKey("appear-refresh"))
- {
- bool newValue;
-
- // FIXME: This can only come from the console at the moment but might not always be true.
- if (ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, options["appear-refresh"], out newValue))
- m_scene.SendPeriodicAppearanceUpdates = newValue;
- }
-
- if (options.ContainsKey("child-repri"))
- {
- double newValue;
-
- // FIXME: This can only come from the console at the moment but might not always be true.
- if (ConsoleUtil.TryParseConsoleDouble(MainConsole.Instance, options["child-repri"], out newValue))
- m_scene.ChildReprioritizationDistance = newValue;
- }
-
- if (options.ContainsKey("client-pos-upd"))
- {
- float newValue;
-
- // FIXME: This can only come from the console at the moment but might not always be true.
- if (ConsoleUtil.TryParseConsoleFloat(MainConsole.Instance, options["client-pos-upd"], out newValue))
- m_scene.RootPositionUpdateTolerance = newValue;
- }
-
- if (options.ContainsKey("client-rot-upd"))
- {
- float newValue;
-
- // FIXME: This can only come from the console at the moment but might not always be true.
- if (ConsoleUtil.TryParseConsoleFloat(MainConsole.Instance, options["client-rot-upd"], out newValue))
- m_scene.RootRotationUpdateTolerance = newValue;
- }
-
- if (options.ContainsKey("client-vel-upd"))
- {
- float newValue;
-
- // FIXME: This can only come from the console at the moment but might not always be true.
- if (ConsoleUtil.TryParseConsoleFloat(MainConsole.Instance, options["client-vel-upd"], out newValue))
- m_scene.RootVelocityUpdateTolerance = newValue;
- }
-
- if (options.ContainsKey("root-upd-per"))
- {
- int newValue;
-
- // FIXME: This can only come from the console at the moment but might not always be true.
- if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, options["root-upd-per"], out newValue))
- m_scene.RootTerseUpdatePeriod = newValue;
- }
-
- if (options.ContainsKey("child-upd-per"))
- {
- int newValue;
-
- // FIXME: This can only come from the console at the moment but might not always be true.
- if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, options["child-upd-per"], out newValue))
- m_scene.ChildTerseUpdatePeriod = newValue;
- }
-
if (options.ContainsKey("pbackup"))
{
bool active;
@@ -308,21 +221,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
m_scene.DebugTeleporting = enableTeleportDebugging;
}
- if (options.ContainsKey("update-on-timer"))
- {
- bool enableUpdateOnTimer;
- if (bool.TryParse(options["update-on-timer"], out enableUpdateOnTimer))
- {
- m_scene.UpdateOnTimer = enableUpdateOnTimer;
- m_scene.Active = false;
-
- while (m_scene.IsRunning)
- Thread.Sleep(20);
-
- m_scene.Active = true;
- }
- }
-
if (options.ContainsKey("updates"))
{
bool enableUpdateDebugging;
@@ -334,4 +232,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
}
}
}
-}
\ No newline at end of file
+}
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 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Reflection;
using System.Timers;
+using System.Threading;
+using System.Xml;
+using System.Xml.Serialization;
+
using OpenMetaverse;
using log4net;
using Mono.Addins;
@@ -38,17 +43,15 @@ using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
-using System.Xml;
-using System.Xml.Serialization;
-using System.IO;
+using Timer= System.Timers.Timer;
namespace OpenSim.Region.OptionalModules.World.TreePopulator
{
///
- /// Version 2.02 - Still hacky
+ /// Version 2.02 - Still hacky
///
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TreePopulatorModule")]
- public class TreePopulatorModule : INonSharedRegionModule, ICommandableModule, IVegetationModule
+ public class TreePopulatorModule : INonSharedRegionModule, ICommandableModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private readonly Commander m_commander = new Commander("tree");
@@ -60,7 +63,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
public string m_name;
public Boolean m_frozen;
public Tree m_tree_type;
- public int m_tree_quantity;
+ public int m_tree_quantity;
public float m_treeline_low;
public float m_treeline_high;
public Vector3 m_seed_point;
@@ -78,24 +81,24 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
{
}
- public Copse(string fileName, Boolean planted)
+ public Copse(string fileName, Boolean planted)
{
Copse cp = (Copse)DeserializeObject(fileName);
- this.m_name = cp.m_name;
- this.m_frozen = cp.m_frozen;
- this.m_tree_quantity = cp.m_tree_quantity;
- this.m_treeline_high = cp.m_treeline_high;
- this.m_treeline_low = cp.m_treeline_low;
- this.m_range = cp.m_range;
- this.m_tree_type = cp.m_tree_type;
- this.m_seed_point = cp.m_seed_point;
- this.m_initial_scale = cp.m_initial_scale;
- this.m_maximum_scale = cp.m_maximum_scale;
- this.m_initial_scale = cp.m_initial_scale;
- this.m_rate = cp.m_rate;
- this.m_planted = planted;
- this.m_trees = new List();
+ m_name = cp.m_name;
+ m_frozen = cp.m_frozen;
+ m_tree_quantity = cp.m_tree_quantity;
+ m_treeline_high = cp.m_treeline_high;
+ m_treeline_low = cp.m_treeline_low;
+ m_range = cp.m_range;
+ m_tree_type = cp.m_tree_type;
+ m_seed_point = cp.m_seed_point;
+ m_initial_scale = cp.m_initial_scale;
+ m_maximum_scale = cp.m_maximum_scale;
+ m_initial_scale = cp.m_initial_scale;
+ m_rate = cp.m_rate;
+ m_planted = planted;
+ m_trees = new List();
}
public Copse(string copsedef)
@@ -103,61 +106,63 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
char[] delimiterChars = {':', ';'};
string[] field = copsedef.Split(delimiterChars);
- this.m_name = field[1].Trim();
- this.m_frozen = (copsedef[0] == 'F');
- this.m_tree_quantity = int.Parse(field[2]);
- this.m_treeline_high = float.Parse(field[3], Culture.NumberFormatInfo);
- this.m_treeline_low = float.Parse(field[4], Culture.NumberFormatInfo);
- this.m_range = double.Parse(field[5], Culture.NumberFormatInfo);
- this.m_tree_type = (Tree) Enum.Parse(typeof(Tree),field[6]);
- this.m_seed_point = Vector3.Parse(field[7]);
- this.m_initial_scale = Vector3.Parse(field[8]);
- this.m_maximum_scale = Vector3.Parse(field[9]);
- this.m_rate = Vector3.Parse(field[10]);
- this.m_planted = true;
- this.m_trees = new List();
+ m_name = field[1].Trim();
+ m_frozen = (copsedef[0] == 'F');
+ m_tree_quantity = int.Parse(field[2]);
+ m_treeline_high = float.Parse(field[3], Culture.NumberFormatInfo);
+ m_treeline_low = float.Parse(field[4], Culture.NumberFormatInfo);
+ m_range = double.Parse(field[5], Culture.NumberFormatInfo);
+ m_tree_type = (Tree) Enum.Parse(typeof(Tree),field[6]);
+ m_seed_point = Vector3.Parse(field[7]);
+ m_initial_scale = Vector3.Parse(field[8]);
+ m_maximum_scale = Vector3.Parse(field[9]);
+ m_rate = Vector3.Parse(field[10]);
+ m_planted = true;
+ m_trees = new List();
}
public Copse(string name, int quantity, float high, float low, double range, Vector3 point, Tree type, Vector3 scale, Vector3 max_scale, Vector3 rate, List trees)
{
- this.m_name = name;
- this.m_frozen = false;
- this.m_tree_quantity = quantity;
- this.m_treeline_high = high;
- this.m_treeline_low = low;
- this.m_range = range;
- this.m_tree_type = type;
- this.m_seed_point = point;
- this.m_initial_scale = scale;
- this.m_maximum_scale = max_scale;
- this.m_rate = rate;
- this.m_planted = false;
- this.m_trees = trees;
+ m_name = name;
+ m_frozen = false;
+ m_tree_quantity = quantity;
+ m_treeline_high = high;
+ m_treeline_low = low;
+ m_range = range;
+ m_tree_type = type;
+ m_seed_point = point;
+ m_initial_scale = scale;
+ m_maximum_scale = max_scale;
+ m_rate = rate;
+ m_planted = false;
+ m_trees = trees;
}
public override string ToString()
{
- string frozen = (this.m_frozen ? "F" : "A");
+ string frozen = (m_frozen ? "F" : "A");
- 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};",
+ 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};",
frozen,
- this.m_name,
- this.m_tree_quantity,
- this.m_treeline_high,
- this.m_treeline_low,
- this.m_range,
- this.m_tree_type,
- this.m_seed_point.ToString(),
- this.m_initial_scale.ToString(),
- this.m_maximum_scale.ToString(),
- this.m_rate.ToString());
+ m_name,
+ m_tree_quantity,
+ m_treeline_high,
+ m_treeline_low,
+ m_range,
+ m_tree_type,
+ m_seed_point.ToString(),
+ m_initial_scale.ToString(),
+ m_maximum_scale.ToString(),
+ m_rate.ToString());
}
}
- private List m_copse;
-
- private double m_update_ms = 1000.0; // msec between updates
+ private List m_copses = new List();
+ private object mylock;
+ private double m_update_ms = 1000.0; // msec between updates
private bool m_active_trees = false;
+ private bool m_enabled = true; // original default
+ private bool m_allowGrow = true; // original default
Timer CalculateTrees;
@@ -174,51 +179,51 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
public void Initialise(IConfigSource config)
{
-
- // ini file settings
- try
+ IConfig moduleConfig = config.Configs["Trees"];
+ if (moduleConfig != null)
{
- m_active_trees = config.Configs["Trees"].GetBoolean("active_trees", m_active_trees);
- }
- catch (Exception)
- {
- m_log.Debug("[TREES]: ini failure for active_trees - using default");
+ m_enabled = moduleConfig.GetBoolean("enabled", m_enabled);
+ m_active_trees = moduleConfig.GetBoolean("active_trees", m_active_trees);
+ m_allowGrow = moduleConfig.GetBoolean("allowGrow", m_allowGrow);
+ m_update_ms = moduleConfig.GetDouble("update_rate", m_update_ms);
}
- try
- {
- m_update_ms = config.Configs["Trees"].GetDouble("update_rate", m_update_ms);
- }
- catch (Exception)
- {
- m_log.Debug("[TREES]: ini failure for update_rate - using default");
- }
+ if(!m_enabled)
+ return;
+
+ m_copses = new List();
+ mylock = new object();
InstallCommands();
- m_log.Debug("[TREES]: Initialised tree module");
+ m_log.Debug("[TREES]: Initialised tree populator module");
}
public void AddRegion(Scene scene)
{
+ if(!m_enabled)
+ return;
m_scene = scene;
m_scene.RegisterModuleCommander(m_commander);
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
-
+ m_scene.EventManager.OnPrimsLoaded += EventManager_OnPrimsLoaded;
}
public void RemoveRegion(Scene scene)
{
- }
+ if(!m_enabled)
+ return;
+ if(m_active_trees && CalculateTrees != null)
+ {
+ CalculateTrees.Dispose();
+ CalculateTrees = null;
+ }
+ m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
+ m_scene.EventManager.OnPrimsLoaded -= EventManager_OnPrimsLoaded;
+ }
public void RegionLoaded(Scene scene)
{
- ReloadCopse();
- if (m_copse.Count > 0)
- m_log.Info("[TREES]: Copse load complete");
-
- if (m_active_trees)
- activeizeTreeze(true);
}
public void Close()
@@ -240,6 +245,16 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
//--------------------------------------------------------------
+ private void EventManager_OnPrimsLoaded(Scene s)
+ {
+ ReloadCopse();
+ if (m_copses.Count > 0)
+ m_log.Info("[TREES]: Copses loaded" );
+
+ if (m_active_trees)
+ activeizeTreeze(true);
+ }
+
#region ICommandableModule Members
private void HandleTreeActive(Object[] args)
@@ -267,25 +282,57 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
string copsename = ((string)args[0]).Trim();
Boolean freezeState = (Boolean) args[1];
- foreach (Copse cp in m_copse)
+ lock(mylock)
{
- if (cp.m_name == copsename && (!cp.m_frozen && freezeState || cp.m_frozen && !freezeState))
+ foreach (Copse cp in m_copses)
{
- cp.m_frozen = freezeState;
- foreach (UUID tree in cp.m_trees)
+ if (cp.m_name != copsename)
+ continue;
+
+ if(!cp.m_frozen && freezeState || cp.m_frozen && !freezeState)
{
- SceneObjectPart sop = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
- sop.Name = (freezeState ? sop.Name.Replace("ATPM", "FTPM") : sop.Name.Replace("FTPM", "ATPM"));
- sop.ParentGroup.HasGroupChanged = true;
- }
+ cp.m_frozen = freezeState;
+ List losttrees = new List();
+ foreach (UUID tree in cp.m_trees)
+ {
+ SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
+ if(sog != null && !sog.IsDeleted)
+ {
+ SceneObjectPart sop = sog.RootPart;
+ string name = sop.Name;
+ if(freezeState)
+ {
+ if(name.StartsWith("FTPM"))
+ continue;
+ if(!name.StartsWith("ATPM"))
+ continue;
+ sop.Name = sop.Name.Replace("ATPM", "FTPM");
+ }
+ else
+ {
+ if(name.StartsWith("ATPM"))
+ continue;
+ if(!name.StartsWith("FTPM"))
+ continue;
+ sop.Name = sop.Name.Replace("FTPM", "ATPM");
+ }
+ sop.ParentGroup.HasGroupChanged = true;
+ sog.ScheduleGroupForFullUpdate();
+ }
+ else
+ losttrees.Add(tree);
+ }
+ foreach (UUID tree in losttrees)
+ cp.m_trees.Remove(tree);
- m_log.InfoFormat("[TREES]: Activity for copse {0} is frozen {1}", copsename, freezeState);
- return;
- }
- else if (cp.m_name == copsename && (cp.m_frozen && freezeState || !cp.m_frozen && !freezeState))
- {
- m_log.InfoFormat("[TREES]: Copse {0} is already in the requested freeze state", copsename);
- return;
+ m_log.InfoFormat("[TREES]: Activity for copse {0} is frozen {1}", copsename, freezeState);
+ return;
+ }
+ else
+ {
+ m_log.InfoFormat("[TREES]: Copse {0} is already in the requested freeze state", copsename);
+ return;
+ }
}
}
m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename);
@@ -297,17 +344,21 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
m_log.InfoFormat("[TREES]: Loading copse definition....");
- copse = new Copse(((string)args[0]), false);
- foreach (Copse cp in m_copse)
+ lock(mylock)
{
- if (cp.m_name == copse.m_name)
+ copse = new Copse(((string)args[0]), false);
{
- m_log.InfoFormat("[TREES]: Copse: {0} is already defined - command failed", copse.m_name);
- return;
+ foreach (Copse cp in m_copses)
+ {
+ if (cp.m_name == copse.m_name)
+ {
+ m_log.InfoFormat("[TREES]: Copse: {0} is already defined - command failed", copse.m_name);
+ return;
+ }
+ }
}
+ m_copses.Add(copse);
}
-
- m_copse.Add(copse);
m_log.InfoFormat("[TREES]: Loaded copse: {0}", copse.ToString());
}
@@ -318,20 +369,24 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
m_log.InfoFormat("[TREES]: New tree planting for copse {0}", copsename);
UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
- foreach (Copse copse in m_copse)
+ lock(mylock)
{
- if (copse.m_name == copsename)
+ foreach (Copse copse in m_copses)
{
- if (!copse.m_planted)
- {
- // The first tree for a copse is created here
- CreateTree(uuid, copse, copse.m_seed_point);
- copse.m_planted = true;
- return;
- }
- else
+ if (copse.m_name == copsename)
{
- m_log.InfoFormat("[TREES]: Copse {0} has already been planted", copsename);
+ if (!copse.m_planted)
+ {
+ // The first tree for a copse is created here
+ CreateTree(uuid, copse, copse.m_seed_point, true);
+ copse.m_planted = true;
+ return;
+ }
+ else
+ {
+ m_log.InfoFormat("[TREES]: Copse {0} has already been planted", copsename);
+ return;
+ }
}
}
}
@@ -376,45 +431,49 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
string copsename = ((string)args[0]).Trim();
Copse copseIdentity = null;
- foreach (Copse cp in m_copse)
+ lock(mylock)
{
- if (cp.m_name == copsename)
+ foreach (Copse cp in m_copses)
{
- copseIdentity = cp;
+ if (cp.m_name == copsename)
+ {
+ copseIdentity = cp;
+ }
}
- }
- if (copseIdentity != null)
- {
- foreach (UUID tree in copseIdentity.m_trees)
+ if (copseIdentity != null)
{
- if (m_scene.Entities.ContainsKey(tree))
- {
- SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
- // Delete tree and alert clients (not silent)
- m_scene.DeleteSceneObject(selectedTree.ParentGroup, false);
- }
- else
+ foreach (UUID tree in copseIdentity.m_trees)
{
- m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
+ if (m_scene.Entities.ContainsKey(tree))
+ {
+ SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
+ // Delete tree and alert clients (not silent)
+ m_scene.DeleteSceneObject(selectedTree.ParentGroup, false);
+ }
+ else
+ {
+ m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
+ }
}
+ copseIdentity.m_trees = null;
+ m_copses.Remove(copseIdentity);
+ m_log.InfoFormat("[TREES]: Copse {0} has been removed", copsename);
+ }
+ else
+ {
+ m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename);
}
- copseIdentity.m_trees = new List();
- m_copse.Remove(copseIdentity);
- m_log.InfoFormat("[TREES]: Copse {0} has been removed", copsename);
- }
- else
- {
- m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename);
}
}
private void HandleTreeStatistics(Object[] args)
{
- m_log.InfoFormat("[TREES]: Activity State: {0}; Update Rate: {1}", m_active_trees, m_update_ms);
- foreach (Copse cp in m_copse)
+ m_log.InfoFormat("[TREES]: region {0}:", m_scene.Name);
+ m_log.InfoFormat("[TREES]: Activity State: {0}; Update Rate: {1}", m_active_trees, m_update_ms);
+ foreach (Copse cp in m_copses)
{
- m_log.InfoFormat("[TREES]: Copse {0}; {1} trees; frozen {2}", cp.m_name, cp.m_trees.Count, cp.m_frozen);
+ m_log.InfoFormat("[TREES]: Copse {0}; {1} trees; frozen {2}", cp.m_name, cp.m_trees.Count, cp.m_frozen);
}
}
@@ -442,7 +501,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
treeRateCommand.AddArgument("updateRate", "The required update rate (minimum 1000.0)", "Double");
Command treeReloadCommand =
- new Command("reload", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeReload, "Reload copse definitions from the in-scene trees");
+ new Command("reload", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeReload, "Reload copses from the in-scene trees");
Command treeRemoveCommand =
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
treeShape.Scale = scale;
treeShape.State = (byte)treeType;
- return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape);
- }
-
- #endregion
-
- #region IEntityCreator Members
-
- protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.NewTree, PCode.Tree };
- public PCode[] CreationCapabilities { get { return creationCapabilities; } }
-
- public SceneObjectGroup CreateEntity(
- UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
- {
- if (Array.IndexOf(creationCapabilities, (PCode)shape.PCode) < 0)
- {
- m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name);
- return null;
- }
-
- SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape);
- SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID);
+ SceneObjectGroup sog = new SceneObjectGroup(uuid, position, rotation, treeShape);
+ SceneObjectPart rootPart = sog.RootPart;
rootPart.AddFlag(PrimFlags.Phantom);
- m_scene.AddNewSceneObject(sceneObject, true);
- sceneObject.SetGroup(groupID, null);
-
- return sceneObject;
+ sog.SetGroup(groupID, null);
+ m_scene.AddNewSceneObject(sog, true, false);
+ sog.IsSelected = false;
+ rootPart.IsSelected = false;
+ sog.InvalidateEffectivePerms();
+ return sog;
}
#endregion
@@ -569,26 +611,27 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
private void ReloadCopse()
{
- m_copse = new List();
+ m_copses = new List();
- EntityBase[] objs = m_scene.GetEntities();
- foreach (EntityBase obj in objs)
+ List grps = m_scene.GetSceneObjectGroups();
+ foreach (SceneObjectGroup grp in grps)
{
- if (obj is SceneObjectGroup)
- {
- SceneObjectGroup grp = (SceneObjectGroup)obj;
+ if(grp.RootPart.Shape.PCode != (byte)PCode.NewTree && grp.RootPart.Shape.PCode != (byte)PCode.Tree)
+ continue;
- if (grp.Name.Length > 5 && (grp.Name.Substring(0, 5) == "ATPM:" || grp.Name.Substring(0, 5) == "FTPM:"))
+ if (grp.Name.Length > 5 && (grp.Name.Substring(0, 5) == "ATPM:" || grp.Name.Substring(0, 5) == "FTPM:"))
+ {
+ // Create a new copse definition or add uuid to an existing definition
+ try
{
- // Create a new copse definition or add uuid to an existing definition
- try
- {
- Boolean copsefound = false;
- Copse copse = new Copse(grp.Name);
+ Boolean copsefound = false;
+ Copse grpcopse = new Copse(grp.Name);
- foreach (Copse cp in m_copse)
+ lock(mylock)
+ {
+ foreach (Copse cp in m_copses)
{
- if (cp.m_name == copse.m_name)
+ if (cp.m_name == grpcopse.m_name)
{
copsefound = true;
cp.m_trees.Add(grp.UUID);
@@ -598,15 +641,15 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
if (!copsefound)
{
- m_log.InfoFormat("[TREES]: Found copse {0}", grp.Name);
- m_copse.Add(copse);
- copse.m_trees.Add(grp.UUID);
+ m_log.InfoFormat("[TREES]: adding copse {0}", grpcopse.m_name);
+ grpcopse.m_trees.Add(grp.UUID);
+ m_copses.Add(grpcopse);
}
}
- catch
- {
- m_log.InfoFormat("[TREES]: Ill formed copse definition {0} - ignoring", grp.Name);
- }
+ }
+ catch
+ {
+ m_log.InfoFormat("[TREES]: Ill formed copse definition {0} - ignoring", grp.Name);
}
}
}
@@ -617,166 +660,265 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
{
if (activeYN)
{
- CalculateTrees = new Timer(m_update_ms);
+ if(CalculateTrees == null)
+ CalculateTrees = new Timer(m_update_ms);
CalculateTrees.Elapsed += CalculateTrees_Elapsed;
+ CalculateTrees.AutoReset = false;
CalculateTrees.Start();
}
- else
+ else
{
CalculateTrees.Stop();
}
- }
+ }
private void growTrees()
{
- foreach (Copse copse in m_copse)
+ if(!m_allowGrow)
+ return;
+
+ foreach (Copse copse in m_copses)
{
- if (!copse.m_frozen)
+ if (copse.m_frozen)
+ continue;
+
+ if(copse.m_trees.Count == 0)
+ continue;
+
+ float maxscale = copse.m_maximum_scale.Z;
+ float ratescale = 1.0f;
+ List losttrees = new List();
+ foreach (UUID tree in copse.m_trees)
{
- foreach (UUID tree in copse.m_trees)
- {
- if (m_scene.Entities.ContainsKey(tree))
- {
- SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
+ SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
- 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)
- {
- s_tree.Scale += copse.m_rate;
- s_tree.ParentGroup.HasGroupChanged = true;
- s_tree.ScheduleFullUpdate();
- }
- }
- else
+ if (sog != null && !sog.IsDeleted)
+ {
+ SceneObjectPart s_tree = sog.RootPart;
+ if (s_tree.Scale.Z < maxscale)
{
- m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
+ ratescale = (float)Util.RandomClass.NextDouble();
+ if(ratescale < 0.2f)
+ ratescale = 0.2f;
+ s_tree.Scale += copse.m_rate * ratescale;
+ sog.HasGroupChanged = true;
+ s_tree.ScheduleFullUpdate();
}
}
+ else
+ losttrees.Add(tree);
}
+
+ foreach (UUID tree in losttrees)
+ copse.m_trees.Remove(tree);
}
}
private void seedTrees()
{
- foreach (Copse copse in m_copse)
+ foreach (Copse copse in m_copses)
{
- if (!copse.m_frozen)
+ if (copse.m_frozen)
+ continue;
+
+ if(copse.m_trees.Count == 0)
+ return;
+
+ bool low = copse.m_trees.Count < (int)(copse.m_tree_quantity * 0.8f);
+
+ if (!low && Util.RandomClass.NextDouble() < 0.75)
+ return;
+
+ int maxbirths = (int)(copse.m_tree_quantity) - copse.m_trees.Count;
+ if(maxbirths <= 1)
+ return;
+
+ if(maxbirths > 20)
+ maxbirths = 20;
+
+ float minscale = 0;
+ if(!low && m_allowGrow)
+ minscale = copse.m_maximum_scale.Z * 0.75f;;
+
+ int i = 0;
+ UUID[] current = copse.m_trees.ToArray();
+ while(--maxbirths > 0)
{
- foreach (UUID tree in copse.m_trees)
+ if(current.Length > 1)
+ i = Util.RandomClass.Next(current.Length -1);
+
+ UUID tree = current[i];
+ SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
+
+ if (sog != null && !sog.IsDeleted)
{
- if (m_scene.Entities.ContainsKey(tree))
- {
- SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
+ SceneObjectPart s_tree = sog.RootPart;
- if (copse.m_trees.Count < copse.m_tree_quantity)
- {
- // Tree has grown enough to seed if it has grown by at least 25% of seeded to full grown height
- if (s_tree.Scale.Z > copse.m_initial_scale.Z + (copse.m_maximum_scale.Z - copse.m_initial_scale.Z) / 4.0)
- {
- if (Util.RandomClass.NextDouble() > 0.75)
- {
- SpawnChild(copse, s_tree);
- }
- }
- }
- }
- else
- {
- m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
- }
+ // Tree has grown enough to seed if it has grown by at least 25% of seeded to full grown height
+ if (s_tree.Scale.Z > minscale)
+ SpawnChild(copse, s_tree, true);
}
- }
+ else if(copse.m_trees.Contains(tree))
+ copse.m_trees.Remove(tree);
+ }
}
}
private void killTrees()
{
- foreach (Copse copse in m_copse)
+ foreach (Copse copse in m_copses)
{
- if (!copse.m_frozen && copse.m_trees.Count >= copse.m_tree_quantity)
- {
- foreach (UUID tree in copse.m_trees)
- {
- double killLikelyhood = 0.0;
+ if (copse.m_frozen)
+ continue;
- if (m_scene.Entities.ContainsKey(tree))
- {
- SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
- double selectedTreeScale = Math.Sqrt(Math.Pow(selectedTree.Scale.X, 2) +
- Math.Pow(selectedTree.Scale.Y, 2) +
- Math.Pow(selectedTree.Scale.Z, 2));
-
- foreach (UUID picktree in copse.m_trees)
- {
- if (picktree != tree)
- {
- SceneObjectPart pickedTree = ((SceneObjectGroup)m_scene.Entities[picktree]).RootPart;
-
- double pickedTreeScale = Math.Sqrt(Math.Pow(pickedTree.Scale.X, 2) +
- Math.Pow(pickedTree.Scale.Y, 2) +
- Math.Pow(pickedTree.Scale.Z, 2));
+ if (Util.RandomClass.NextDouble() < 0.25)
+ return;
- double pickedTreeDistance = Vector3.Distance(pickedTree.AbsolutePosition, selectedTree.AbsolutePosition);
+ int maxbdeaths = copse.m_trees.Count - (int)(copse.m_tree_quantity * .98f) ;
+ if(maxbdeaths < 1)
+ return;
- killLikelyhood += (selectedTreeScale / (pickedTreeScale * pickedTreeDistance)) * 0.1;
- }
- }
+ float odds;
+ float scale = 1.0f / copse.m_maximum_scale.Z;
- if (Util.RandomClass.NextDouble() < killLikelyhood)
- {
- // Delete tree and alert clients (not silent)
- m_scene.DeleteSceneObject(selectedTree.ParentGroup, false);
- copse.m_trees.Remove(selectedTree.ParentGroup.UUID);
- break;
- }
+ int ntries = maxbdeaths * 4;
+ while(ntries-- > 0 )
+ {
+ int next = 0;
+ if (copse.m_trees.Count > 1)
+ next = Util.RandomClass.Next(copse.m_trees.Count - 1);
+ UUID tree = copse.m_trees[next];
+ SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
+ if (sog != null && !sog.IsDeleted)
+ {
+ if(m_allowGrow)
+ {
+ odds = sog.RootPart.Scale.Z * scale;
+ odds = odds * odds * odds;
+ odds *= (float)Util.RandomClass.NextDouble();
}
else
{
- m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
+ odds = (float)Util.RandomClass.NextDouble();
+ odds = odds * odds * odds;
}
+
+ if(odds > 0.9f)
+ {
+ m_scene.DeleteSceneObject(sog, false);
+ if(maxbdeaths <= 0)
+ break;
+ }
+ }
+ else
+ {
+ copse.m_trees.Remove(tree);
+ if(copse.m_trees.Count - (int)(copse.m_tree_quantity * .98f) <= 0 )
+ break;
}
}
}
}
- private void SpawnChild(Copse copse, SceneObjectPart s_tree)
+ private void SpawnChild(Copse copse, SceneObjectPart s_tree, bool low)
{
Vector3 position = new Vector3();
-
- double randX = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3);
- double randY = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3);
-
+
+ float randX = copse.m_maximum_scale.X * 1.25f;
+ float randY = copse.m_maximum_scale.Y * 1.25f;
+
+ float r = (float)Util.RandomClass.NextDouble();
+ randX *= 2.0f * r - 1.0f;
position.X = s_tree.AbsolutePosition.X + (float)randX;
+
+ r = (float)Util.RandomClass.NextDouble();
+ randY *= 2.0f * r - 1.0f;
position.Y = s_tree.AbsolutePosition.Y + (float)randY;
- if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 &&
- position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 &&
- Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range)
- {
- UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
+ if (position.X > (m_scene.RegionInfo.RegionSizeX - 1) || position.X <= 0 ||
+ position.Y > (m_scene.RegionInfo.RegionSizeY - 1) || position.Y <= 0)
+ return;
- CreateTree(uuid, copse, position);
- }
+ randX = position.X - copse.m_seed_point.X;
+ randX *= randX;
+ randY = position.Y - copse.m_seed_point.Y;
+ randY *= randY;
+ randX += randY;
+
+ if(randX > copse.m_range * copse.m_range)
+ return;
+
+ UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
+ CreateTree(uuid, copse, position, low);
}
- private void CreateTree(UUID uuid, Copse copse, Vector3 position)
+ private void CreateTree(UUID uuid, Copse copse, Vector3 position, bool randomScale)
{
-
position.Z = (float)m_scene.Heightmap[(int)position.X, (int)position.Y];
- if (position.Z >= copse.m_treeline_low && position.Z <= copse.m_treeline_high)
- {
- SceneObjectGroup tree = AddTree(uuid, UUID.Zero, copse.m_initial_scale, Quaternion.Identity, position, copse.m_tree_type, false);
+ if (position.Z < copse.m_treeline_low || position.Z > copse.m_treeline_high)
+ return;
- tree.Name = copse.ToString();
- copse.m_trees.Add(tree.UUID);
- tree.SendGroupFullUpdate();
+ Vector3 scale = copse.m_initial_scale;
+ if(randomScale)
+ {
+ try
+ {
+ float t;
+ float r = (float)Util.RandomClass.NextDouble();
+ r *= (float)Util.RandomClass.NextDouble();
+ r *= (float)Util.RandomClass.NextDouble();
+
+ t = copse.m_maximum_scale.X / copse.m_initial_scale.X;
+ if(t < 1.0)
+ t = 1 / t;
+ t = t * r + 1.0f;
+ scale.X *= t;
+
+ t = copse.m_maximum_scale.Y / copse.m_initial_scale.Y;
+ if(t < 1.0)
+ t = 1 / t;
+ t = t * r + 1.0f;
+ scale.Y *= t;
+
+ t = copse.m_maximum_scale.Z / copse.m_initial_scale.Z;
+ if(t < 1.0)
+ t = 1 / t;
+ t = t * r + 1.0f;
+ scale.Z *= t;
+ }
+ catch
+ {
+ scale = copse.m_initial_scale;
+ }
}
+
+ SceneObjectGroup tree = AddTree(uuid, UUID.Zero, scale, Quaternion.Identity, position, copse.m_tree_type, false);
+ tree.Name = copse.ToString();
+ copse.m_trees.Add(tree.UUID);
+ tree.RootPart.ScheduleFullUpdate();
}
private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e)
{
- growTrees();
- seedTrees();
- killTrees();
+ if(!m_scene.IsRunning)
+ return;
+
+ if(Monitor.TryEnter(mylock))
+ {
+ try
+ {
+ if(m_scene.LoginsEnabled )
+ {
+ growTrees();
+ seedTrees();
+ killTrees();
+ }
+ }
+ catch { }
+ if(CalculateTrees != null)
+ CalculateTrees.Start();
+ Monitor.Exit(mylock);
+ }
}
}
}
--
cgit v1.1