diff options
Diffstat (limited to 'OpenSim')
42 files changed, 1218 insertions, 633 deletions
diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs index 546b5e8..70e1065 100644 --- a/OpenSim/Data/IRegionData.cs +++ b/OpenSim/Data/IRegionData.cs | |||
@@ -85,21 +85,6 @@ namespace OpenSim.Data | |||
85 | List<RegionData> GetHyperlinks(UUID scopeID); | 85 | List<RegionData> GetHyperlinks(UUID scopeID); |
86 | } | 86 | } |
87 | 87 | ||
88 | [Flags] | ||
89 | public enum RegionFlags : int | ||
90 | { | ||
91 | DefaultRegion = 1, // Used for new Rez. Random if multiple defined | ||
92 | FallbackRegion = 2, // Regions we redirect to when the destination is down | ||
93 | RegionOnline = 4, // Set when a region comes online, unset when it unregisters and DeleteOnUnregister is false | ||
94 | NoDirectLogin = 8, // Region unavailable for direct logins (by name) | ||
95 | Persistent = 16, // Don't remove on unregister | ||
96 | LockedOut = 32, // Don't allow registration | ||
97 | NoMove = 64, // Don't allow moving this region | ||
98 | Reservation = 128, // This is an inactive reservation | ||
99 | Authenticate = 256, // Require authentication | ||
100 | Hyperlink = 512 // Record represents a HG link | ||
101 | } | ||
102 | |||
103 | public class RegionDataDistanceCompare : IComparer<RegionData> | 88 | public class RegionDataDistanceCompare : IComparer<RegionData> |
104 | { | 89 | { |
105 | private Vector2 m_origin; | 90 | private Vector2 m_origin; |
diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs index 3ae87c3..0d89706 100644 --- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs | |||
@@ -37,6 +37,7 @@ using OpenMetaverse; | |||
37 | using OpenSim.Framework; | 37 | using OpenSim.Framework; |
38 | using OpenSim.Region.Framework.Interfaces; | 38 | using OpenSim.Region.Framework.Interfaces; |
39 | using OpenSim.Region.Framework.Scenes; | 39 | using OpenSim.Region.Framework.Scenes; |
40 | using RegionFlags = OpenSim.Framework.RegionFlags; | ||
40 | 41 | ||
41 | namespace OpenSim.Data.MSSQL | 42 | namespace OpenSim.Data.MSSQL |
42 | { | 43 | { |
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs index 0614879..a2d4ae4 100644 --- a/OpenSim/Data/MySQL/MySQLRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLRegionData.cs | |||
@@ -30,11 +30,11 @@ using System.Collections; | |||
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Data; | 31 | using System.Data; |
32 | using System.Reflection; | 32 | using System.Reflection; |
33 | 33 | using MySql.Data.MySqlClient; | |
34 | using OpenMetaverse; | 34 | using OpenMetaverse; |
35 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
36 | using OpenSim.Data; | 36 | using OpenSim.Data; |
37 | using MySql.Data.MySqlClient; | 37 | using RegionFlags = OpenSim.Framework.RegionFlags; |
38 | 38 | ||
39 | namespace OpenSim.Data.MySQL | 39 | namespace OpenSim.Data.MySQL |
40 | { | 40 | { |
diff --git a/OpenSim/Data/Null/NullRegionData.cs b/OpenSim/Data/Null/NullRegionData.cs index deb50cb..b4d701a 100644 --- a/OpenSim/Data/Null/NullRegionData.cs +++ b/OpenSim/Data/Null/NullRegionData.cs | |||
@@ -33,6 +33,7 @@ using OpenSim.Framework; | |||
33 | using OpenSim.Data; | 33 | using OpenSim.Data; |
34 | using System.Reflection; | 34 | using System.Reflection; |
35 | using log4net; | 35 | using log4net; |
36 | using RegionFlags = OpenSim.Framework.RegionFlags; | ||
36 | 37 | ||
37 | namespace OpenSim.Data.Null | 38 | namespace OpenSim.Data.Null |
38 | { | 39 | { |
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs index 2612a50..a7cf0c0 100644 --- a/OpenSim/Framework/Console/ConsoleUtil.cs +++ b/OpenSim/Framework/Console/ConsoleUtil.cs | |||
@@ -34,7 +34,7 @@ using OpenMetaverse; | |||
34 | 34 | ||
35 | public class ConsoleUtil | 35 | public class ConsoleUtil |
36 | { | 36 | { |
37 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 37 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
38 | 38 | ||
39 | public const string MinRawConsoleVectorValue = "-~"; | 39 | public const string MinRawConsoleVectorValue = "-~"; |
40 | public const string MaxRawConsoleVectorValue = "~"; | 40 | public const string MaxRawConsoleVectorValue = "~"; |
@@ -107,7 +107,7 @@ public class ConsoleUtil | |||
107 | 107 | ||
108 | string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); | 108 | string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); |
109 | 109 | ||
110 | m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector); | 110 | // m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector); |
111 | 111 | ||
112 | return Vector3.TryParse(semiDigestedConsoleVector, out vector); | 112 | return Vector3.TryParse(semiDigestedConsoleVector, out vector); |
113 | } | 113 | } |
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index 8ac9090..aa86202 100644 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | |||
@@ -359,13 +359,19 @@ Asset service request failures: {3}" + Environment.NewLine, | |||
359 | inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, | 359 | inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, |
360 | netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); | 360 | netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); |
361 | 361 | ||
362 | foreach (KeyValuePair<string, Stat> kvp in StatsManager.RegisteredStats) | 362 | Dictionary<string, Dictionary<string, Stat>> sceneStats; |
363 | { | ||
364 | Stat stat = kvp.Value; | ||
365 | 363 | ||
366 | if (stat.Category == "scene" && stat.Verbosity == StatVerbosity.Info) | 364 | if (StatsManager.TryGetStats("scene", out sceneStats)) |
365 | { | ||
366 | foreach (KeyValuePair<string, Dictionary<string, Stat>> kvp in sceneStats) | ||
367 | { | 367 | { |
368 | sb.AppendFormat("Slow frames ({0}): {1}\n", stat.Container, stat.Value); | 368 | foreach (Stat stat in kvp.Value.Values) |
369 | { | ||
370 | if (stat.Verbosity == StatVerbosity.Info) | ||
371 | { | ||
372 | sb.AppendFormat("{0} ({1}): {2}{3}\n", stat.Name, stat.Container, stat.Value, stat.UnitName); | ||
373 | } | ||
374 | } | ||
369 | } | 375 | } |
370 | } | 376 | } |
371 | 377 | ||
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index b5dc24f..31989e5 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs | |||
@@ -35,13 +35,23 @@ namespace OpenSim.Framework.Monitoring | |||
35 | /// </summary> | 35 | /// </summary> |
36 | public class StatsManager | 36 | public class StatsManager |
37 | { | 37 | { |
38 | // Subcommand used to list other stats. | ||
39 | public const string AllSubCommand = "all"; | ||
40 | |||
41 | // Subcommand used to list other stats. | ||
42 | public const string ListSubCommand = "list"; | ||
43 | |||
44 | // All subcommands | ||
45 | public static HashSet<string> SubCommands = new HashSet<string> { AllSubCommand, ListSubCommand }; | ||
46 | |||
38 | /// <summary> | 47 | /// <summary> |
39 | /// Registered stats. | 48 | /// Registered stats categorized by category/container/shortname |
40 | /// </summary> | 49 | /// </summary> |
41 | /// <remarks> | 50 | /// <remarks> |
42 | /// Do not add or remove from this dictionary. | 51 | /// Do not add or remove directly from this dictionary. |
43 | /// </remarks> | 52 | /// </remarks> |
44 | public static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>(); | 53 | public static Dictionary<string, Dictionary<string, Dictionary<string, Stat>>> RegisteredStats |
54 | = new Dictionary<string, Dictionary<string, Dictionary<string, Stat>>>(); | ||
45 | 55 | ||
46 | private static AssetStatsCollector assetStats; | 56 | private static AssetStatsCollector assetStats; |
47 | private static UserStatsCollector userStats; | 57 | private static UserStatsCollector userStats; |
@@ -51,6 +61,75 @@ namespace OpenSim.Framework.Monitoring | |||
51 | public static UserStatsCollector UserStats { get { return userStats; } } | 61 | public static UserStatsCollector UserStats { get { return userStats; } } |
52 | public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } | 62 | public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } |
53 | 63 | ||
64 | public static void RegisterConsoleCommands(ICommandConsole console) | ||
65 | { | ||
66 | console.Commands.AddCommand( | ||
67 | "General", | ||
68 | false, | ||
69 | "show stats", | ||
70 | "show stats [list|all|<category>]", | ||
71 | "Show statistical information for this server", | ||
72 | "If no final argument is specified then legacy statistics information is currently shown.\n" | ||
73 | + "If list is specified then statistic categories are shown.\n" | ||
74 | + "If all is specified then all registered statistics are shown.\n" | ||
75 | + "If a category name is specified then only statistics from that category are shown.\n" | ||
76 | + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", | ||
77 | HandleShowStatsCommand); | ||
78 | } | ||
79 | |||
80 | public static void HandleShowStatsCommand(string module, string[] cmd) | ||
81 | { | ||
82 | ICommandConsole con = MainConsole.Instance; | ||
83 | |||
84 | if (cmd.Length > 2) | ||
85 | { | ||
86 | var categoryName = cmd[2]; | ||
87 | |||
88 | if (categoryName == AllSubCommand) | ||
89 | { | ||
90 | foreach (var category in RegisteredStats.Values) | ||
91 | { | ||
92 | OutputCategoryStatsToConsole(con, category); | ||
93 | } | ||
94 | } | ||
95 | else if (categoryName == ListSubCommand) | ||
96 | { | ||
97 | con.Output("Statistic categories available are:"); | ||
98 | foreach (string category in RegisteredStats.Keys) | ||
99 | con.OutputFormat(" {0}", category); | ||
100 | } | ||
101 | else | ||
102 | { | ||
103 | Dictionary<string, Dictionary<string, Stat>> category; | ||
104 | if (!RegisteredStats.TryGetValue(categoryName, out category)) | ||
105 | { | ||
106 | con.OutputFormat("No such category as {0}", categoryName); | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | OutputCategoryStatsToConsole(con, category); | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | else | ||
115 | { | ||
116 | // Legacy | ||
117 | con.Output(SimExtraStats.Report()); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | private static void OutputCategoryStatsToConsole( | ||
122 | ICommandConsole con, Dictionary<string, Dictionary<string, Stat>> category) | ||
123 | { | ||
124 | foreach (var container in category.Values) | ||
125 | { | ||
126 | foreach (Stat stat in container.Values) | ||
127 | { | ||
128 | con.Output(stat.ToConsoleString()); | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | |||
54 | /// <summary> | 133 | /// <summary> |
55 | /// Start collecting statistics related to assets. | 134 | /// Start collecting statistics related to assets. |
56 | /// Should only be called once. | 135 | /// Should only be called once. |
@@ -73,43 +152,100 @@ namespace OpenSim.Framework.Monitoring | |||
73 | return userStats; | 152 | return userStats; |
74 | } | 153 | } |
75 | 154 | ||
155 | /// <summary> | ||
156 | /// Registers a statistic. | ||
157 | /// </summary> | ||
158 | /// <param name='stat'></param> | ||
159 | /// <returns></returns> | ||
76 | public static bool RegisterStat(Stat stat) | 160 | public static bool RegisterStat(Stat stat) |
77 | { | 161 | { |
162 | Dictionary<string, Dictionary<string, Stat>> category = null, newCategory; | ||
163 | Dictionary<string, Stat> container = null, newContainer; | ||
164 | |||
78 | lock (RegisteredStats) | 165 | lock (RegisteredStats) |
79 | { | 166 | { |
80 | if (RegisteredStats.ContainsKey(stat.UniqueName)) | 167 | // Stat name is not unique across category/container/shortname key. |
81 | { | 168 | // XXX: For now just return false. This is to avoid problems in regression tests where all tests |
82 | // XXX: For now just return false. This is to avoid problems in regression tests where all tests | 169 | // in a class are run in the same instance of the VM. |
83 | // in a class are run in the same instance of the VM. | 170 | if (TryGetStat(stat, out category, out container)) |
84 | return false; | 171 | return false; |
85 | 172 | ||
86 | // throw new Exception( | 173 | // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. |
87 | // "StatsManager already contains stat with ShortName {0} in Category {1}", stat.ShortName, stat.Category); | 174 | // This means that we don't need to lock or copy them on iteration, which will be a much more |
88 | } | 175 | // common operation after startup. |
176 | if (container != null) | ||
177 | newContainer = new Dictionary<string, Stat>(container); | ||
178 | else | ||
179 | newContainer = new Dictionary<string, Stat>(); | ||
89 | 180 | ||
90 | // We take a replace-on-write approach here so that we don't need to generate a new Dictionary | 181 | if (category != null) |
91 | Dictionary<string, Stat> newRegisteredStats = new Dictionary<string, Stat>(RegisteredStats); | 182 | newCategory = new Dictionary<string, Dictionary<string, Stat>>(category); |
92 | newRegisteredStats[stat.UniqueName] = stat; | 183 | else |
93 | RegisteredStats = newRegisteredStats; | 184 | newCategory = new Dictionary<string, Dictionary<string, Stat>>(); |
185 | |||
186 | newContainer[stat.ShortName] = stat; | ||
187 | newCategory[stat.Container] = newContainer; | ||
188 | RegisteredStats[stat.Category] = newCategory; | ||
94 | } | 189 | } |
95 | 190 | ||
96 | return true; | 191 | return true; |
97 | } | 192 | } |
98 | 193 | ||
194 | /// <summary> | ||
195 | /// Deregister a statistic | ||
196 | /// </summary>> | ||
197 | /// <param name='stat'></param> | ||
198 | /// <returns></returns | ||
99 | public static bool DeregisterStat(Stat stat) | 199 | public static bool DeregisterStat(Stat stat) |
100 | { | 200 | { |
201 | Dictionary<string, Dictionary<string, Stat>> category = null, newCategory; | ||
202 | Dictionary<string, Stat> container = null, newContainer; | ||
203 | |||
101 | lock (RegisteredStats) | 204 | lock (RegisteredStats) |
102 | { | 205 | { |
103 | if (!RegisteredStats.ContainsKey(stat.UniqueName)) | 206 | if (!TryGetStat(stat, out category, out container)) |
104 | return false; | 207 | return false; |
105 | 208 | ||
106 | Dictionary<string, Stat> newRegisteredStats = new Dictionary<string, Stat>(RegisteredStats); | 209 | newContainer = new Dictionary<string, Stat>(container); |
107 | newRegisteredStats.Remove(stat.UniqueName); | 210 | newContainer.Remove(stat.UniqueName); |
108 | RegisteredStats = newRegisteredStats; | 211 | |
212 | newCategory = new Dictionary<string, Dictionary<string, Stat>>(category); | ||
213 | newCategory.Remove(stat.Container); | ||
214 | |||
215 | newCategory[stat.Container] = newContainer; | ||
216 | RegisteredStats[stat.Category] = newCategory; | ||
109 | 217 | ||
110 | return true; | 218 | return true; |
111 | } | 219 | } |
112 | } | 220 | } |
221 | |||
222 | public static bool TryGetStats(string category, out Dictionary<string, Dictionary<string, Stat>> stats) | ||
223 | { | ||
224 | return RegisteredStats.TryGetValue(category, out stats); | ||
225 | } | ||
226 | |||
227 | public static bool TryGetStat( | ||
228 | Stat stat, | ||
229 | out Dictionary<string, Dictionary<string, Stat>> category, | ||
230 | out Dictionary<string, Stat> container) | ||
231 | { | ||
232 | category = null; | ||
233 | container = null; | ||
234 | |||
235 | lock (RegisteredStats) | ||
236 | { | ||
237 | if (RegisteredStats.TryGetValue(stat.Category, out category)) | ||
238 | { | ||
239 | if (category.TryGetValue(stat.Container, out container)) | ||
240 | { | ||
241 | if (container.ContainsKey(stat.ShortName)) | ||
242 | return true; | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | |||
247 | return false; | ||
248 | } | ||
113 | } | 249 | } |
114 | 250 | ||
115 | /// <summary> | 251 | /// <summary> |
@@ -157,9 +293,26 @@ namespace OpenSim.Framework.Monitoring | |||
157 | 293 | ||
158 | public virtual double Value { get; set; } | 294 | public virtual double Value { get; set; } |
159 | 295 | ||
296 | /// <summary> | ||
297 | /// Constructor | ||
298 | /// </summary> | ||
299 | /// <param name='shortName'>Short name for the stat. Must not contain spaces. e.g. "LongFrames"</param> | ||
300 | /// <param name='name'>Human readable name for the stat. e.g. "Long frames"</param> | ||
301 | /// <param name='unitName'> | ||
302 | /// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value. | ||
303 | /// e.g. " frames" | ||
304 | /// </param> | ||
305 | /// <param name='category'>Category under which this stat should appear, e.g. "scene". Do not capitalize.</param> | ||
306 | /// <param name='container'>Entity to which this stat relates. e.g. scene name if this is a per scene stat.</param> | ||
307 | /// <param name='verbosity'>Verbosity of stat. Controls whether it will appear in short stat display or only full display.</param> | ||
308 | /// <param name='description'>Description of stat</param> | ||
160 | public Stat( | 309 | public Stat( |
161 | string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description) | 310 | string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description) |
162 | { | 311 | { |
312 | if (StatsManager.SubCommands.Contains(category)) | ||
313 | throw new Exception( | ||
314 | string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category)); | ||
315 | |||
163 | ShortName = shortName; | 316 | ShortName = shortName; |
164 | Name = name; | 317 | Name = name; |
165 | UnitName = unitName; | 318 | UnitName = unitName; |
@@ -175,6 +328,12 @@ namespace OpenSim.Framework.Monitoring | |||
175 | { | 328 | { |
176 | return string.Format("{0}+{1}+{2}", container, category, shortName); | 329 | return string.Format("{0}+{1}+{2}", container, category, shortName); |
177 | } | 330 | } |
331 | |||
332 | public virtual string ToConsoleString() | ||
333 | { | ||
334 | return string.Format( | ||
335 | "{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName); | ||
336 | } | ||
178 | } | 337 | } |
179 | 338 | ||
180 | public class PercentageStat : Stat | 339 | public class PercentageStat : Stat |
@@ -192,7 +351,7 @@ namespace OpenSim.Framework.Monitoring | |||
192 | if (c == 0) | 351 | if (c == 0) |
193 | return 0; | 352 | return 0; |
194 | 353 | ||
195 | return (double)Antecedent / c; | 354 | return (double)Antecedent / c * 100; |
196 | } | 355 | } |
197 | 356 | ||
198 | set | 357 | set |
@@ -203,8 +362,13 @@ namespace OpenSim.Framework.Monitoring | |||
203 | 362 | ||
204 | public PercentageStat( | 363 | public PercentageStat( |
205 | string shortName, string name, string category, string container, StatVerbosity verbosity, string description) | 364 | string shortName, string name, string category, string container, StatVerbosity verbosity, string description) |
206 | : base(shortName, name, " %", category, container, verbosity, description) | 365 | : base(shortName, name, "%", category, container, verbosity, description) {} |
366 | |||
367 | public override string ToConsoleString() | ||
207 | { | 368 | { |
369 | return string.Format( | ||
370 | "{0}.{1}.{2} : {3:0.##}{4} ({5}/{6})", | ||
371 | Category, Container, ShortName, Value, UnitName, Antecedent, Consequent); | ||
208 | } | 372 | } |
209 | } | 373 | } |
210 | } \ No newline at end of file | 374 | } \ No newline at end of file |
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs index eaddb8c..28d6d5c 100644 --- a/OpenSim/Framework/Monitoring/Watchdog.cs +++ b/OpenSim/Framework/Monitoring/Watchdog.cs | |||
@@ -231,7 +231,25 @@ namespace OpenSim.Framework.Monitoring | |||
231 | private static bool RemoveThread(int threadID) | 231 | private static bool RemoveThread(int threadID) |
232 | { | 232 | { |
233 | lock (m_threads) | 233 | lock (m_threads) |
234 | return m_threads.Remove(threadID); | 234 | { |
235 | ThreadWatchdogInfo twi; | ||
236 | if (m_threads.TryGetValue(threadID, out twi)) | ||
237 | { | ||
238 | m_log.DebugFormat( | ||
239 | "[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId); | ||
240 | |||
241 | m_threads.Remove(threadID); | ||
242 | |||
243 | return true; | ||
244 | } | ||
245 | else | ||
246 | { | ||
247 | m_log.WarnFormat( | ||
248 | "[WATCHDOG]: Requested to remove thread with ID {0} but this is not being monitored", threadID); | ||
249 | |||
250 | return false; | ||
251 | } | ||
252 | } | ||
235 | } | 253 | } |
236 | 254 | ||
237 | public static bool AbortThread(int threadID) | 255 | public static bool AbortThread(int threadID) |
diff --git a/OpenSim/Framework/RegionFlags.cs b/OpenSim/Framework/RegionFlags.cs new file mode 100644 index 0000000..a3089b0 --- /dev/null +++ b/OpenSim/Framework/RegionFlags.cs | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | |||
30 | namespace OpenSim.Framework | ||
31 | { | ||
32 | /// <summary> | ||
33 | /// Region flags used internally by OpenSimulator to store installation specific information about regions. | ||
34 | /// </summary> | ||
35 | /// <remarks> | ||
36 | /// Don't confuse with OpenMetaverse.RegionFlags which are client facing flags (i.e. they go over the wire). | ||
37 | /// Returned by IGridService.GetRegionFlags() | ||
38 | /// </remarks> | ||
39 | [Flags] | ||
40 | public enum RegionFlags : int | ||
41 | { | ||
42 | DefaultRegion = 1, // Used for new Rez. Random if multiple defined | ||
43 | FallbackRegion = 2, // Regions we redirect to when the destination is down | ||
44 | RegionOnline = 4, // Set when a region comes online, unset when it unregisters and DeleteOnUnregister is false | ||
45 | NoDirectLogin = 8, // Region unavailable for direct logins (by name) | ||
46 | Persistent = 16, // Don't remove on unregister | ||
47 | LockedOut = 32, // Don't allow registration | ||
48 | NoMove = 64, // Don't allow moving this region | ||
49 | Reservation = 128, // This is an inactive reservation | ||
50 | Authenticate = 256, // Require authentication | ||
51 | Hyperlink = 512 // Record represents a HG link | ||
52 | } | ||
53 | } \ No newline at end of file | ||
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index cf19002..a8f3a9e 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs | |||
@@ -96,11 +96,6 @@ namespace OpenSim.Framework.Servers | |||
96 | get { return m_httpServer; } | 96 | get { return m_httpServer; } |
97 | } | 97 | } |
98 | 98 | ||
99 | /// <summary> | ||
100 | /// Holds the non-viewer statistics collection object for this service/server | ||
101 | /// </summary> | ||
102 | protected IStatsCollector m_stats; | ||
103 | |||
104 | public BaseOpenSimServer() | 99 | public BaseOpenSimServer() |
105 | { | 100 | { |
106 | m_startuptime = DateTime.Now; | 101 | m_startuptime = DateTime.Now; |
@@ -177,10 +172,6 @@ namespace OpenSim.Framework.Servers | |||
177 | "show info", | 172 | "show info", |
178 | "Show general information about the server", HandleShow); | 173 | "Show general information about the server", HandleShow); |
179 | 174 | ||
180 | m_console.Commands.AddCommand("General", false, "show stats", | ||
181 | "show stats", | ||
182 | "Show statistics", HandleShow); | ||
183 | |||
184 | m_console.Commands.AddCommand("General", false, "show threads", | 175 | m_console.Commands.AddCommand("General", false, "show threads", |
185 | "show threads", | 176 | "show threads", |
186 | "Show thread status", HandleShow); | 177 | "Show thread status", HandleShow); |
@@ -226,12 +217,7 @@ namespace OpenSim.Framework.Servers | |||
226 | { | 217 | { |
227 | StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n"); | 218 | StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n"); |
228 | sb.Append(GetUptimeReport()); | 219 | sb.Append(GetUptimeReport()); |
229 | 220 | sb.Append(StatsManager.SimExtraStats.Report()); | |
230 | if (m_stats != null) | ||
231 | { | ||
232 | sb.Append(m_stats.Report()); | ||
233 | } | ||
234 | |||
235 | sb.Append(Environment.NewLine); | 221 | sb.Append(Environment.NewLine); |
236 | sb.Append(GetThreadsReport()); | 222 | sb.Append(GetThreadsReport()); |
237 | 223 | ||
@@ -382,10 +368,6 @@ namespace OpenSim.Framework.Servers | |||
382 | { | 368 | { |
383 | Notice("set log level [level] - change the console logging level only. For example, off or debug."); | 369 | Notice("set log level [level] - change the console logging level only. For example, off or debug."); |
384 | Notice("show info - show server information (e.g. startup path)."); | 370 | Notice("show info - show server information (e.g. startup path)."); |
385 | |||
386 | if (m_stats != null) | ||
387 | Notice("show stats - show statistical information for this server"); | ||
388 | |||
389 | Notice("show threads - list tracked threads"); | 371 | Notice("show threads - list tracked threads"); |
390 | Notice("show uptime - show server startup time and uptime."); | 372 | Notice("show uptime - show server startup time and uptime."); |
391 | Notice("show version - show server version."); | 373 | Notice("show version - show server version."); |
@@ -409,11 +391,6 @@ namespace OpenSim.Framework.Servers | |||
409 | ShowInfo(); | 391 | ShowInfo(); |
410 | break; | 392 | break; |
411 | 393 | ||
412 | case "stats": | ||
413 | if (m_stats != null) | ||
414 | Notice(m_stats.Report()); | ||
415 | break; | ||
416 | |||
417 | case "threads": | 394 | case "threads": |
418 | Notice(GetThreadsReport()); | 395 | Notice(GetThreadsReport()); |
419 | break; | 396 | break; |
@@ -604,8 +581,7 @@ namespace OpenSim.Framework.Servers | |||
604 | 581 | ||
605 | public string osSecret { | 582 | public string osSecret { |
606 | // Secret uuid for the simulator | 583 | // Secret uuid for the simulator |
607 | get { return m_osSecret; } | 584 | get { return m_osSecret; } |
608 | |||
609 | } | 585 | } |
610 | 586 | ||
611 | public string StatReport(IOSHttpRequest httpRequest) | 587 | public string StatReport(IOSHttpRequest httpRequest) |
@@ -613,11 +589,11 @@ namespace OpenSim.Framework.Servers | |||
613 | // If we catch a request for "callback", wrap the response in the value for jsonp | 589 | // If we catch a request for "callback", wrap the response in the value for jsonp |
614 | if (httpRequest.Query.ContainsKey("callback")) | 590 | if (httpRequest.Query.ContainsKey("callback")) |
615 | { | 591 | { |
616 | return httpRequest.Query["callback"].ToString() + "(" + m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");"; | 592 | return httpRequest.Query["callback"].ToString() + "(" + StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");"; |
617 | } | 593 | } |
618 | else | 594 | else |
619 | { | 595 | { |
620 | return m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); | 596 | return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); |
621 | } | 597 | } |
622 | } | 598 | } |
623 | 599 | ||
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index a9b2745..3d4dce1 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -254,8 +254,14 @@ namespace OpenSim | |||
254 | m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); | 254 | m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); |
255 | 255 | ||
256 | m_console.Commands.AddCommand("Debug", false, "debug scene", | 256 | m_console.Commands.AddCommand("Debug", false, "debug scene", |
257 | "debug scene <scripting> <collisions> <physics>", | 257 | "debug scene active|collisions|physics|scripting|teleport true|false", |
258 | "Turn on scene debugging", Debug); | 258 | "Turn on scene debugging.", |
259 | "If active is false then main scene update and maintenance loops are suspended.\n" | ||
260 | + "If collisions is false then collisions with other objects are turned off.\n" | ||
261 | + "If physics is false then all physics objects are non-physical.\n" | ||
262 | + "If scripting is false then no scripting operations happen.\n" | ||
263 | + "If teleport is true then some extra teleport debug information is logged.", | ||
264 | Debug); | ||
259 | 265 | ||
260 | m_console.Commands.AddCommand("General", false, "change region", | 266 | m_console.Commands.AddCommand("General", false, "change region", |
261 | "change region <region name>", | 267 | "change region <region name>", |
@@ -930,7 +936,8 @@ namespace OpenSim | |||
930 | } | 936 | } |
931 | else | 937 | else |
932 | { | 938 | { |
933 | MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false"); | 939 | MainConsole.Instance.Output( |
940 | "Usage: debug scene active|scripting|collisions|physics|teleport true|false"); | ||
934 | } | 941 | } |
935 | 942 | ||
936 | break; | 943 | break; |
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index d107b7a..b410a0e 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs | |||
@@ -232,8 +232,6 @@ namespace OpenSim | |||
232 | 232 | ||
233 | base.StartupSpecific(); | 233 | base.StartupSpecific(); |
234 | 234 | ||
235 | m_stats = StatsManager.SimExtraStats; | ||
236 | |||
237 | // Create a ModuleLoader instance | 235 | // Create a ModuleLoader instance |
238 | m_moduleLoader = new ModuleLoader(m_config.Source); | 236 | m_moduleLoader = new ModuleLoader(m_config.Source); |
239 | 237 | ||
@@ -249,51 +247,51 @@ namespace OpenSim | |||
249 | plugin.PostInitialise(); | 247 | plugin.PostInitialise(); |
250 | } | 248 | } |
251 | 249 | ||
252 | AddPluginCommands(); | 250 | if (m_console != null) |
251 | { | ||
252 | StatsManager.RegisterConsoleCommands(m_console); | ||
253 | AddPluginCommands(m_console); | ||
254 | } | ||
253 | } | 255 | } |
254 | 256 | ||
255 | protected virtual void AddPluginCommands() | 257 | protected virtual void AddPluginCommands(CommandConsole console) |
256 | { | 258 | { |
257 | // If console exists add plugin commands. | 259 | List<string> topics = GetHelpTopics(); |
258 | if (m_console != null) | ||
259 | { | ||
260 | List<string> topics = GetHelpTopics(); | ||
261 | 260 | ||
262 | foreach (string topic in topics) | 261 | foreach (string topic in topics) |
263 | { | 262 | { |
264 | string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); | 263 | string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); |
265 | 264 | ||
266 | // This is a hack to allow the user to enter the help command in upper or lowercase. This will go | 265 | // This is a hack to allow the user to enter the help command in upper or lowercase. This will go |
267 | // away at some point. | 266 | // away at some point. |
268 | m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, | 267 | console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, |
269 | "help " + capitalizedTopic, | 268 | "help " + capitalizedTopic, |
270 | "Get help on plugin command '" + topic + "'", | 269 | "Get help on plugin command '" + topic + "'", |
271 | HandleCommanderHelp); | 270 | HandleCommanderHelp); |
272 | m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, | 271 | console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, |
273 | "help " + capitalizedTopic, | 272 | "help " + capitalizedTopic, |
274 | "Get help on plugin command '" + topic + "'", | 273 | "Get help on plugin command '" + topic + "'", |
275 | HandleCommanderHelp); | 274 | HandleCommanderHelp); |
276 | 275 | ||
277 | ICommander commander = null; | 276 | ICommander commander = null; |
278 | 277 | ||
279 | Scene s = SceneManager.CurrentOrFirstScene; | 278 | Scene s = SceneManager.CurrentOrFirstScene; |
280 | 279 | ||
281 | if (s != null && s.GetCommanders() != null) | 280 | if (s != null && s.GetCommanders() != null) |
282 | { | 281 | { |
283 | if (s.GetCommanders().ContainsKey(topic)) | 282 | if (s.GetCommanders().ContainsKey(topic)) |
284 | commander = s.GetCommanders()[topic]; | 283 | commander = s.GetCommanders()[topic]; |
285 | } | 284 | } |
286 | 285 | ||
287 | if (commander == null) | 286 | if (commander == null) |
288 | continue; | 287 | continue; |
289 | 288 | ||
290 | foreach (string command in commander.Commands.Keys) | 289 | foreach (string command in commander.Commands.Keys) |
291 | { | 290 | { |
292 | m_console.Commands.AddCommand(capitalizedTopic, false, | 291 | console.Commands.AddCommand(capitalizedTopic, false, |
293 | topic + " " + command, | 292 | topic + " " + command, |
294 | topic + " " + commander.Commands[command].ShortHelp(), | 293 | topic + " " + commander.Commands[command].ShortHelp(), |
295 | String.Empty, HandleCommanderCommand); | 294 | String.Empty, HandleCommanderCommand); |
296 | } | ||
297 | } | 295 | } |
298 | } | 296 | } |
299 | } | 297 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index e113c60..132546b 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | |||
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
94 | 94 | ||
95 | //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); | 95 | //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); |
96 | 96 | ||
97 | scene.EventManager.OnNewClient += OnNewClient; | 97 | // scene.EventManager.OnNewClient += OnNewClient; |
98 | 98 | ||
99 | // TODO: Leaving these open, or closing them when we | 99 | // TODO: Leaving these open, or closing them when we |
100 | // become a child is incorrect. It messes up TP in a big | 100 | // become a child is incorrect. It messes up TP in a big |
@@ -102,6 +102,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
102 | // circuit is there. | 102 | // circuit is there. |
103 | 103 | ||
104 | scene.EventManager.OnClientClosed += ClientClosed; | 104 | scene.EventManager.OnClientClosed += ClientClosed; |
105 | |||
105 | scene.EventManager.OnMakeChildAgent += MakeChildAgent; | 106 | scene.EventManager.OnMakeChildAgent += MakeChildAgent; |
106 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; | 107 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; |
107 | 108 | ||
@@ -226,16 +227,6 @@ namespace OpenSim.Region.ClientStack.Linden | |||
226 | 227 | ||
227 | #endregion | 228 | #endregion |
228 | 229 | ||
229 | private void OnNewClient(IClientAPI client) | ||
230 | { | ||
231 | //client.OnLogout += ClientClosed; | ||
232 | } | ||
233 | |||
234 | // private void ClientClosed(IClientAPI client) | ||
235 | // { | ||
236 | // ClientClosed(client.AgentId); | ||
237 | // } | ||
238 | |||
239 | private void ClientClosed(UUID agentID, Scene scene) | 230 | private void ClientClosed(UUID agentID, Scene scene) |
240 | { | 231 | { |
241 | // m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); | 232 | // m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6ccabf1..d04bd96 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -47,6 +47,7 @@ using OpenSim.Region.Framework.Scenes; | |||
47 | using OpenSim.Services.Interfaces; | 47 | using OpenSim.Services.Interfaces; |
48 | using Timer = System.Timers.Timer; | 48 | using Timer = System.Timers.Timer; |
49 | using AssetLandmark = OpenSim.Framework.AssetLandmark; | 49 | using AssetLandmark = OpenSim.Framework.AssetLandmark; |
50 | using RegionFlags = OpenMetaverse.RegionFlags; | ||
50 | using Nini.Config; | 51 | using Nini.Config; |
51 | 52 | ||
52 | using System.IO; | 53 | using System.IO; |
@@ -3983,7 +3984,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3983 | { | 3984 | { |
3984 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; | 3985 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; |
3985 | 3986 | ||
3986 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); | 3987 | ImprovedTerseObjectUpdatePacket packet |
3988 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
3987 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 3989 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
3988 | packet.RegionData.TimeDilation = timeDilation; | 3990 | packet.RegionData.TimeDilation = timeDilation; |
3989 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | 3991 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; |
@@ -4028,7 +4030,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4028 | { | 4030 | { |
4029 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; | 4031 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; |
4030 | 4032 | ||
4031 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); | 4033 | ImprovedTerseObjectUpdatePacket packet |
4034 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( | ||
4035 | PacketType.ImprovedTerseObjectUpdate); | ||
4032 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 4036 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
4033 | packet.RegionData.TimeDilation = timeDilation; | 4037 | packet.RegionData.TimeDilation = timeDilation; |
4034 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | 4038 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; |
@@ -4036,7 +4040,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4036 | for (int i = 0; i < blocks.Count; i++) | 4040 | for (int i = 0; i < blocks.Count; i++) |
4037 | packet.ObjectData[i] = blocks[i]; | 4041 | packet.ObjectData[i] = blocks[i]; |
4038 | 4042 | ||
4039 | OutPacket(packet, ThrottleOutPacketType.Task, true); | 4043 | OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); |
4040 | } | 4044 | } |
4041 | 4045 | ||
4042 | #endregion Packet Sending | 4046 | #endregion Packet Sending |
@@ -5037,7 +5041,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5037 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; | 5041 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; |
5038 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; | 5042 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; |
5039 | 5043 | ||
5040 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); | 5044 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock block |
5045 | = PacketPool.Instance.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); | ||
5046 | |||
5041 | block.Data = data; | 5047 | block.Data = data; |
5042 | 5048 | ||
5043 | if (textureEntry != null && textureEntry.Length > 0) | 5049 | if (textureEntry != null && textureEntry.Length > 0) |
@@ -11949,7 +11955,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11949 | logPacket = false; | 11955 | logPacket = false; |
11950 | 11956 | ||
11951 | if (DebugPacketLevel <= 50 | 11957 | if (DebugPacketLevel <= 50 |
11952 | & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) | 11958 | && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) |
11953 | logPacket = false; | 11959 | logPacket = false; |
11954 | 11960 | ||
11955 | if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) | 11961 | if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) |
@@ -12481,7 +12487,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12481 | ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); | 12487 | ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); |
12482 | 12488 | ||
12483 | 12489 | ||
12484 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); | 12490 | ImprovedTerseObjectUpdatePacket packet |
12491 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( | ||
12492 | PacketType.ImprovedTerseObjectUpdate); | ||
12493 | |||
12485 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 12494 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
12486 | packet.RegionData.TimeDilation = timeDilation; | 12495 | packet.RegionData.TimeDilation = timeDilation; |
12487 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | 12496 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index b3db064..97b79ce 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -100,9 +100,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
100 | 100 | ||
101 | /// <summary>The measured resolution of Environment.TickCount</summary> | 101 | /// <summary>The measured resolution of Environment.TickCount</summary> |
102 | public readonly float TickCountResolution; | 102 | public readonly float TickCountResolution; |
103 | |||
103 | /// <summary>Number of prim updates to put on the queue each time the | 104 | /// <summary>Number of prim updates to put on the queue each time the |
104 | /// OnQueueEmpty event is triggered for updates</summary> | 105 | /// OnQueueEmpty event is triggered for updates</summary> |
105 | public readonly int PrimUpdatesPerCallback; | 106 | public readonly int PrimUpdatesPerCallback; |
107 | |||
106 | /// <summary>Number of texture packets to put on the queue each time the | 108 | /// <summary>Number of texture packets to put on the queue each time the |
107 | /// OnQueueEmpty event is triggered for textures</summary> | 109 | /// OnQueueEmpty event is triggered for textures</summary> |
108 | public readonly int TextureSendLimit; | 110 | public readonly int TextureSendLimit; |
@@ -124,28 +126,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
124 | 126 | ||
125 | /// <summary>Manages authentication for agent circuits</summary> | 127 | /// <summary>Manages authentication for agent circuits</summary> |
126 | private AgentCircuitManager m_circuitManager; | 128 | private AgentCircuitManager m_circuitManager; |
129 | |||
127 | /// <summary>Reference to the scene this UDP server is attached to</summary> | 130 | /// <summary>Reference to the scene this UDP server is attached to</summary> |
128 | protected Scene m_scene; | 131 | protected Scene m_scene; |
132 | |||
129 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> | 133 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> |
130 | private Location m_location; | 134 | private Location m_location; |
135 | |||
131 | /// <summary>The size of the receive buffer for the UDP socket. This value | 136 | /// <summary>The size of the receive buffer for the UDP socket. This value |
132 | /// is passed up to the operating system and used in the system networking | 137 | /// is passed up to the operating system and used in the system networking |
133 | /// stack. Use zero to leave this value as the default</summary> | 138 | /// stack. Use zero to leave this value as the default</summary> |
134 | private int m_recvBufferSize; | 139 | private int m_recvBufferSize; |
140 | |||
135 | /// <summary>Flag to process packets asynchronously or synchronously</summary> | 141 | /// <summary>Flag to process packets asynchronously or synchronously</summary> |
136 | private bool m_asyncPacketHandling; | 142 | private bool m_asyncPacketHandling; |
143 | |||
137 | /// <summary>Tracks whether or not a packet was sent each round so we know | 144 | /// <summary>Tracks whether or not a packet was sent each round so we know |
138 | /// whether or not to sleep</summary> | 145 | /// whether or not to sleep</summary> |
139 | private bool m_packetSent; | 146 | private bool m_packetSent; |
140 | 147 | ||
141 | /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> | 148 | /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> |
142 | private int m_elapsedMSSinceLastStatReport = 0; | 149 | private int m_elapsedMSSinceLastStatReport = 0; |
150 | |||
143 | /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> | 151 | /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> |
144 | private int m_tickLastOutgoingPacketHandler; | 152 | private int m_tickLastOutgoingPacketHandler; |
153 | |||
145 | /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> | 154 | /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> |
146 | private int m_elapsedMSOutgoingPacketHandler; | 155 | private int m_elapsedMSOutgoingPacketHandler; |
156 | |||
147 | /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> | 157 | /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> |
148 | private int m_elapsed100MSOutgoingPacketHandler; | 158 | private int m_elapsed100MSOutgoingPacketHandler; |
159 | |||
149 | /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> | 160 | /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> |
150 | private int m_elapsed500MSOutgoingPacketHandler; | 161 | private int m_elapsed500MSOutgoingPacketHandler; |
151 | 162 | ||
@@ -425,6 +436,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
425 | byte[] data = packet.ToBytes(); | 436 | byte[] data = packet.ToBytes(); |
426 | SendPacketData(udpClient, data, packet.Type, category, method); | 437 | SendPacketData(udpClient, data, packet.Type, category, method); |
427 | } | 438 | } |
439 | |||
440 | PacketPool.Instance.ReturnPacket(packet); | ||
428 | } | 441 | } |
429 | 442 | ||
430 | /// <summary> | 443 | /// <summary> |
@@ -742,7 +755,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
742 | 755 | ||
743 | try | 756 | try |
744 | { | 757 | { |
745 | packet = Packet.BuildPacket(buffer.Data, ref packetEnd, | 758 | // packet = Packet.BuildPacket(buffer.Data, ref packetEnd, |
759 | // // Only allocate a buffer for zerodecoding if the packet is zerocoded | ||
760 | // ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | ||
761 | packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, | ||
746 | // Only allocate a buffer for zerodecoding if the packet is zerocoded | 762 | // Only allocate a buffer for zerodecoding if the packet is zerocoded |
747 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | 763 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); |
748 | } | 764 | } |
@@ -757,11 +773,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
757 | 773 | ||
758 | return; // Drop short packet | 774 | return; // Drop short packet |
759 | } | 775 | } |
760 | catch(Exception e) | 776 | catch (Exception e) |
761 | { | 777 | { |
762 | if (m_malformedCount < 100) | 778 | if (m_malformedCount < 100) |
763 | m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); | 779 | m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); |
780 | |||
764 | m_malformedCount++; | 781 | m_malformedCount++; |
782 | |||
765 | if ((m_malformedCount % 100000) == 0) | 783 | if ((m_malformedCount % 100000) == 0) |
766 | m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); | 784 | m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); |
767 | } | 785 | } |
@@ -1169,20 +1187,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1169 | { | 1187 | { |
1170 | IClientAPI client = null; | 1188 | IClientAPI client = null; |
1171 | 1189 | ||
1172 | // In priciple there shouldn't be more than one thread here, ever. | 1190 | // We currently synchronize this code across the whole scene to avoid issues such as |
1173 | // But in case that happens, we need to synchronize this piece of code | 1191 | // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done |
1174 | // because it's too important | 1192 | // consistently, this lock could probably be removed. |
1175 | lock (this) | 1193 | lock (this) |
1176 | { | 1194 | { |
1177 | if (!m_scene.TryGetClient(agentID, out client)) | 1195 | if (!m_scene.TryGetClient(agentID, out client)) |
1178 | { | 1196 | { |
1179 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); | 1197 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); |
1180 | 1198 | ||
1181 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | 1199 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); |
1182 | client.OnLogout += LogoutHandler; | 1200 | client.OnLogout += LogoutHandler; |
1183 | 1201 | ||
1184 | ((LLClientView)client).DisableFacelights = m_disableFacelights; | 1202 | ((LLClientView)client).DisableFacelights = m_disableFacelights; |
1185 | 1203 | ||
1186 | client.Start(); | 1204 | client.Start(); |
1187 | } | 1205 | } |
1188 | } | 1206 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index fc9406b..71f6fe1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | |||
@@ -31,6 +31,7 @@ using System.Reflection; | |||
31 | using OpenMetaverse; | 31 | using OpenMetaverse; |
32 | using OpenMetaverse.Packets; | 32 | using OpenMetaverse.Packets; |
33 | using log4net; | 33 | using log4net; |
34 | using OpenSim.Framework.Monitoring; | ||
34 | 35 | ||
35 | namespace OpenSim.Region.ClientStack.LindenUDP | 36 | namespace OpenSim.Region.ClientStack.LindenUDP |
36 | { | 37 | { |
@@ -43,17 +44,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
43 | private bool packetPoolEnabled = true; | 44 | private bool packetPoolEnabled = true; |
44 | private bool dataBlockPoolEnabled = true; | 45 | private bool dataBlockPoolEnabled = true; |
45 | 46 | ||
47 | private PercentageStat m_packetsReusedStat = new PercentageStat( | ||
48 | "PacketsReused", | ||
49 | "Packets reused", | ||
50 | "clientstack", | ||
51 | "packetpool", | ||
52 | StatVerbosity.Debug, | ||
53 | "Number of packets reused out of all requests to the packet pool"); | ||
54 | |||
55 | private PercentageStat m_blocksReusedStat = new PercentageStat( | ||
56 | "BlocksReused", | ||
57 | "Blocks reused", | ||
58 | "clientstack", | ||
59 | "packetpool", | ||
60 | StatVerbosity.Debug, | ||
61 | "Number of data blocks reused out of all requests to the packet pool"); | ||
62 | |||
46 | /// <summary> | 63 | /// <summary> |
47 | /// Pool of packets available for reuse. | 64 | /// Pool of packets available for reuse. |
48 | /// </summary> | 65 | /// </summary> |
49 | private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); | 66 | private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); |
50 | 67 | ||
51 | private static Dictionary<Type, Stack<Object>> DataBlocks = | 68 | private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>(); |
52 | new Dictionary<Type, Stack<Object>>(); | ||
53 | |||
54 | static PacketPool() | ||
55 | { | ||
56 | } | ||
57 | 69 | ||
58 | public static PacketPool Instance | 70 | public static PacketPool Instance |
59 | { | 71 | { |
@@ -72,8 +84,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
72 | get { return dataBlockPoolEnabled; } | 84 | get { return dataBlockPoolEnabled; } |
73 | } | 85 | } |
74 | 86 | ||
87 | private PacketPool() | ||
88 | { | ||
89 | StatsManager.RegisterStat(m_packetsReusedStat); | ||
90 | StatsManager.RegisterStat(m_blocksReusedStat); | ||
91 | } | ||
92 | |||
93 | /// <summary> | ||
94 | /// Gets a packet of the given type. | ||
95 | /// </summary> | ||
96 | /// <param name='type'></param> | ||
97 | /// <returns>Guaranteed to always return a packet, whether from the pool or newly constructed.</returns> | ||
75 | public Packet GetPacket(PacketType type) | 98 | public Packet GetPacket(PacketType type) |
76 | { | 99 | { |
100 | m_packetsReusedStat.Consequent++; | ||
101 | |||
77 | Packet packet; | 102 | Packet packet; |
78 | 103 | ||
79 | if (!packetPoolEnabled) | 104 | if (!packetPoolEnabled) |
@@ -89,6 +114,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
89 | else | 114 | else |
90 | { | 115 | { |
91 | // Recycle old packages | 116 | // Recycle old packages |
117 | m_packetsReusedStat.Antecedent++; | ||
118 | |||
92 | packet = (pool[type]).Pop(); | 119 | packet = (pool[type]).Pop(); |
93 | } | 120 | } |
94 | } | 121 | } |
@@ -138,7 +165,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
138 | { | 165 | { |
139 | PacketType type = GetType(bytes); | 166 | PacketType type = GetType(bytes); |
140 | 167 | ||
141 | Array.Clear(zeroBuffer, 0, zeroBuffer.Length); | 168 | // Array.Clear(zeroBuffer, 0, zeroBuffer.Length); |
142 | 169 | ||
143 | int i = 0; | 170 | int i = 0; |
144 | Packet packet = GetPacket(type); | 171 | Packet packet = GetPacket(type); |
@@ -185,6 +212,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
185 | switch (packet.Type) | 212 | switch (packet.Type) |
186 | { | 213 | { |
187 | // List pooling packets here | 214 | // List pooling packets here |
215 | case PacketType.AgentUpdate: | ||
188 | case PacketType.PacketAck: | 216 | case PacketType.PacketAck: |
189 | case PacketType.ObjectUpdate: | 217 | case PacketType.ObjectUpdate: |
190 | case PacketType.ImprovedTerseObjectUpdate: | 218 | case PacketType.ImprovedTerseObjectUpdate: |
@@ -211,16 +239,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
211 | } | 239 | } |
212 | } | 240 | } |
213 | 241 | ||
214 | public static T GetDataBlock<T>() where T: new() | 242 | public T GetDataBlock<T>() where T: new() |
215 | { | 243 | { |
216 | lock (DataBlocks) | 244 | lock (DataBlocks) |
217 | { | 245 | { |
246 | m_blocksReusedStat.Consequent++; | ||
247 | |||
218 | Stack<Object> s; | 248 | Stack<Object> s; |
219 | 249 | ||
220 | if (DataBlocks.TryGetValue(typeof(T), out s)) | 250 | if (DataBlocks.TryGetValue(typeof(T), out s)) |
221 | { | 251 | { |
222 | if (s.Count > 0) | 252 | if (s.Count > 0) |
253 | { | ||
254 | m_blocksReusedStat.Antecedent++; | ||
223 | return (T)s.Pop(); | 255 | return (T)s.Pop(); |
256 | } | ||
224 | } | 257 | } |
225 | else | 258 | else |
226 | { | 259 | { |
@@ -231,7 +264,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
231 | } | 264 | } |
232 | } | 265 | } |
233 | 266 | ||
234 | public static void ReturnDataBlock<T>(T block) where T: new() | 267 | public void ReturnDataBlock<T>(T block) where T: new() |
235 | { | 268 | { |
236 | if (block == null) | 269 | if (block == null) |
237 | return; | 270 | return; |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index 109a8e1..fa9378c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs | |||
@@ -43,7 +43,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
43 | /// This will contain basic tests for the LindenUDP client stack | 43 | /// This will contain basic tests for the LindenUDP client stack |
44 | /// </summary> | 44 | /// </summary> |
45 | [TestFixture] | 45 | [TestFixture] |
46 | public class BasicCircuitTests | 46 | public class BasicCircuitTests : OpenSimTestCase |
47 | { | 47 | { |
48 | private Scene m_scene; | 48 | private Scene m_scene; |
49 | private TestLLUDPServer m_udpServer; | 49 | private TestLLUDPServer m_udpServer; |
@@ -143,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
143 | public void TestAddClient() | 143 | public void TestAddClient() |
144 | { | 144 | { |
145 | TestHelpers.InMethod(); | 145 | TestHelpers.InMethod(); |
146 | // XmlConfigurator.Configure(); | 146 | // TestHelpers.EnableLogging(); |
147 | 147 | ||
148 | AddUdpServer(); | 148 | AddUdpServer(); |
149 | 149 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index a5c4584..0aee0d4 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | |||
@@ -212,7 +212,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
212 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); | 212 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); |
213 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); | 213 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); |
214 | 214 | ||
215 | if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) | 215 | if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) |
216 | { | 216 | { |
217 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); | 217 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); |
218 | GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); | 218 | GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); |
@@ -232,7 +232,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
232 | return true; | 232 | return true; |
233 | 233 | ||
234 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); | 234 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); |
235 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) | 235 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) |
236 | return true; | 236 | return true; |
237 | 237 | ||
238 | return false; | 238 | return false; |
@@ -256,7 +256,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
256 | reason = string.Empty; | 256 | reason = string.Empty; |
257 | logout = false; | 257 | logout = false; |
258 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); | 258 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); |
259 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) | 259 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) |
260 | { | 260 | { |
261 | // this user is going to another grid | 261 | // this user is going to another grid |
262 | // check if HyperGrid teleport is allowed, based on user level | 262 | // check if HyperGrid teleport is allowed, based on user level |
@@ -303,7 +303,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
303 | // The rest is only needed for controlling appearance | 303 | // The rest is only needed for controlling appearance |
304 | 304 | ||
305 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); | 305 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); |
306 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) | 306 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) |
307 | { | 307 | { |
308 | // this user is going to another grid | 308 | // this user is going to another grid |
309 | if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID)) | 309 | if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID)) |
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index fdef9d8..5fd1bce 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | |||
@@ -40,6 +40,7 @@ using OpenMetaverse; | |||
40 | using OpenSim.Framework; | 40 | using OpenSim.Framework; |
41 | using OpenSim.Region.Framework.Interfaces; | 41 | using OpenSim.Region.Framework.Interfaces; |
42 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
43 | using RegionFlags = OpenMetaverse.RegionFlags; | ||
43 | 44 | ||
44 | namespace OpenSim.Region.CoreModules.World.Estate | 45 | namespace OpenSim.Region.CoreModules.World.Estate |
45 | { | 46 | { |
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 4f06737..d5b2adb 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs | |||
@@ -33,6 +33,7 @@ using OpenMetaverse; | |||
33 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
34 | using OpenSim.Region.Framework.Interfaces; | 34 | using OpenSim.Region.Framework.Interfaces; |
35 | using OpenSim.Region.Framework.Scenes; | 35 | using OpenSim.Region.Framework.Scenes; |
36 | using RegionFlags = OpenMetaverse.RegionFlags; | ||
36 | 37 | ||
37 | namespace OpenSim.Region.CoreModules.World.Land | 38 | namespace OpenSim.Region.CoreModules.World.Land |
38 | { | 39 | { |
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 6e39e9a..7a35182 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Linq; | ||
30 | using System.Reflection; | 31 | using System.Reflection; |
31 | using System.Text; | 32 | using System.Text; |
32 | using System.Text.RegularExpressions; | 33 | using System.Text.RegularExpressions; |
@@ -83,29 +84,56 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
83 | m_console.Commands.AddCommand( | 84 | m_console.Commands.AddCommand( |
84 | "Objects", false, "delete object owner", | 85 | "Objects", false, "delete object owner", |
85 | "delete object owner <UUID>", | 86 | "delete object owner <UUID>", |
86 | "Delete a scene object by owner", HandleDeleteObject); | 87 | "Delete scene objects by owner", |
88 | "Command will ask for confirmation before proceeding.", | ||
89 | HandleDeleteObject); | ||
87 | 90 | ||
88 | m_console.Commands.AddCommand( | 91 | m_console.Commands.AddCommand( |
89 | "Objects", false, "delete object creator", | 92 | "Objects", false, "delete object creator", |
90 | "delete object creator <UUID>", | 93 | "delete object creator <UUID>", |
91 | "Delete a scene object by creator", HandleDeleteObject); | 94 | "Delete scene objects by creator", |
95 | "Command will ask for confirmation before proceeding.", | ||
96 | HandleDeleteObject); | ||
92 | 97 | ||
93 | m_console.Commands.AddCommand( | 98 | m_console.Commands.AddCommand( |
94 | "Objects", false, "delete object uuid", | 99 | "Objects", false, "delete object uuid", |
95 | "delete object uuid <UUID>", | 100 | "delete object uuid <UUID>", |
96 | "Delete a scene object by uuid", HandleDeleteObject); | 101 | "Delete a scene object by uuid", |
102 | HandleDeleteObject); | ||
97 | 103 | ||
98 | m_console.Commands.AddCommand( | 104 | m_console.Commands.AddCommand( |
99 | "Objects", false, "delete object name", | 105 | "Objects", false, "delete object name", |
100 | "delete object name [--regex] <name>", | 106 | "delete object name [--regex] <name>", |
101 | "Delete a scene object by name.", | 107 | "Delete a scene object by name.", |
102 | "If --regex is specified then the name is treatead as a regular expression", | 108 | "Command will ask for confirmation before proceeding.\n" |
109 | + "If --regex is specified then the name is treatead as a regular expression", | ||
103 | HandleDeleteObject); | 110 | HandleDeleteObject); |
104 | 111 | ||
105 | m_console.Commands.AddCommand( | 112 | m_console.Commands.AddCommand( |
106 | "Objects", false, "delete object outside", | 113 | "Objects", false, "delete object outside", |
107 | "delete object outside", | 114 | "delete object outside", |
108 | "Delete all scene objects outside region boundaries", HandleDeleteObject); | 115 | "Delete all scene objects outside region boundaries", |
116 | "Command will ask for confirmation before proceeding.", | ||
117 | HandleDeleteObject); | ||
118 | |||
119 | m_console.Commands.AddCommand( | ||
120 | "Objects", | ||
121 | false, | ||
122 | "delete object pos", | ||
123 | "delete object pos <start-coord> to <end-coord>", | ||
124 | "Delete scene objects within the given area.", | ||
125 | "Each component of the coord is comma separated. There must be no spaces between the commas.\n" | ||
126 | + "If you don't care about the z component you can simply omit it.\n" | ||
127 | + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" | ||
128 | + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" | ||
129 | + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" | ||
130 | + "e.g.\n" | ||
131 | + "delete object pos 20,20,20 to 40,40,40\n" | ||
132 | + "delete object pos 20,20 to 40,40\n" | ||
133 | + "delete object pos ,20,20 to ,40,40\n" | ||
134 | + "delete object pos ,,30 to ,,~\n" | ||
135 | + "delete object pos ,,-~ to ,,30", | ||
136 | HandleDeleteObject); | ||
109 | 137 | ||
110 | m_console.Commands.AddCommand( | 138 | m_console.Commands.AddCommand( |
111 | "Objects", | 139 | "Objects", |
@@ -301,23 +329,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
301 | return; | 329 | return; |
302 | } | 330 | } |
303 | 331 | ||
304 | string rawConsoleStartVector = cmdparams[3]; | 332 | Vector3 startVector, endVector; |
305 | Vector3 startVector; | ||
306 | 333 | ||
307 | if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) | 334 | if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) |
308 | { | ||
309 | m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); | ||
310 | return; | 335 | return; |
311 | } | ||
312 | |||
313 | string rawConsoleEndVector = cmdparams[5]; | ||
314 | Vector3 endVector; | ||
315 | |||
316 | if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) | ||
317 | { | ||
318 | m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); | ||
319 | return; | ||
320 | } | ||
321 | 336 | ||
322 | Predicate<SceneObjectGroup> searchPredicate | 337 | Predicate<SceneObjectGroup> searchPredicate |
323 | = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); | 338 | = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); |
@@ -557,6 +572,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
557 | 572 | ||
558 | break; | 573 | break; |
559 | 574 | ||
575 | case "pos": | ||
576 | deletes = GetDeleteCandidatesByPos(module, cmd); | ||
577 | break; | ||
578 | |||
560 | default: | 579 | default: |
561 | m_console.OutputFormat("Unrecognized mode {0}", mode); | 580 | m_console.OutputFormat("Unrecognized mode {0}", mode); |
562 | return; | 581 | return; |
@@ -571,7 +590,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
571 | string.Format( | 590 | string.Format( |
572 | "Are you sure that you want to delete {0} objects from {1}", | 591 | "Are you sure that you want to delete {0} objects from {1}", |
573 | deletes.Count, m_scene.RegionInfo.RegionName), | 592 | deletes.Count, m_scene.RegionInfo.RegionName), |
574 | "n"); | 593 | "y/N"); |
575 | 594 | ||
576 | if (response.ToLower() != "y") | 595 | if (response.ToLower() != "y") |
577 | { | 596 | { |
@@ -593,9 +612,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
593 | 612 | ||
594 | private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams) | 613 | private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams) |
595 | { | 614 | { |
596 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) | ||
597 | return null; | ||
598 | |||
599 | bool useRegex = false; | 615 | bool useRegex = false; |
600 | OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); | 616 | OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); |
601 | 617 | ||
@@ -629,5 +645,52 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
629 | 645 | ||
630 | return sceneObjects; | 646 | return sceneObjects; |
631 | } | 647 | } |
648 | |||
649 | /// <summary> | ||
650 | /// Get scene object delete candidates by position | ||
651 | /// </summary> | ||
652 | /// <param name='module'></param> | ||
653 | /// <param name='cmdparams'></param> | ||
654 | /// <returns>null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there | ||
655 | /// are no objects to delete then the list will be empty./returns> | ||
656 | private List<SceneObjectGroup> GetDeleteCandidatesByPos(string module, string[] cmdparams) | ||
657 | { | ||
658 | if (cmdparams.Length < 5) | ||
659 | { | ||
660 | m_console.OutputFormat("Usage: delete object pos <start-coord> to <end-coord>"); | ||
661 | return null; | ||
662 | } | ||
663 | |||
664 | Vector3 startVector, endVector; | ||
665 | |||
666 | if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) | ||
667 | return null; | ||
668 | |||
669 | return m_scene.GetSceneObjectGroups().FindAll( | ||
670 | so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)); | ||
671 | } | ||
672 | |||
673 | private bool TryParseVectorRange(IEnumerable<string> rawComponents, out Vector3 startVector, out Vector3 endVector) | ||
674 | { | ||
675 | string rawConsoleStartVector = rawComponents.Take(1).Single(); | ||
676 | |||
677 | if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) | ||
678 | { | ||
679 | m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); | ||
680 | endVector = Vector3.Zero; | ||
681 | |||
682 | return false; | ||
683 | } | ||
684 | |||
685 | string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single(); | ||
686 | |||
687 | if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) | ||
688 | { | ||
689 | m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); | ||
690 | return false; | ||
691 | } | ||
692 | |||
693 | return true; | ||
694 | } | ||
632 | } | 695 | } |
633 | } \ No newline at end of file | 696 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 7133817..e2414eb 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs | |||
@@ -125,13 +125,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
125 | /// </summary> | 125 | /// </summary> |
126 | /// <remarks> | 126 | /// <remarks> |
127 | /// This is triggered for both child and root agent client connections. | 127 | /// This is triggered for both child and root agent client connections. |
128 | /// | ||
128 | /// Triggered before OnClientLogin. | 129 | /// Triggered before OnClientLogin. |
130 | /// | ||
131 | /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please | ||
132 | /// do this on a separate thread. | ||
129 | /// </remarks> | 133 | /// </remarks> |
130 | public event OnNewClientDelegate OnNewClient; | 134 | public event OnNewClientDelegate OnNewClient; |
131 | 135 | ||
132 | /// <summary> | 136 | /// <summary> |
133 | /// Fired if the client entering this sim is doing so as a new login | 137 | /// Fired if the client entering this sim is doing so as a new login |
134 | /// </summary> | 138 | /// </summary> |
139 | /// <remarks> | ||
140 | /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please | ||
141 | /// do this on a separate thread. | ||
142 | /// </remarks> | ||
135 | public event Action<IClientAPI> OnClientLogin; | 143 | public event Action<IClientAPI> OnClientLogin; |
136 | 144 | ||
137 | public delegate void OnNewPresenceDelegate(ScenePresence presence); | 145 | public delegate void OnNewPresenceDelegate(ScenePresence presence); |
@@ -153,6 +161,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
153 | /// <remarks> | 161 | /// <remarks> |
154 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both | 162 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both |
155 | /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> | 163 | /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> |
164 | /// | ||
165 | /// Triggered under per-agent lock. So if you want to perform any long-running operations, please | ||
166 | /// do this on a separate thread. | ||
156 | /// </remarks> | 167 | /// </remarks> |
157 | public event OnRemovePresenceDelegate OnRemovePresence; | 168 | public event OnRemovePresenceDelegate OnRemovePresence; |
158 | 169 | ||
@@ -429,6 +440,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
429 | /// </summary> | 440 | /// </summary> |
430 | /// <remarks> | 441 | /// <remarks> |
431 | /// At the point of firing, the scene still contains the client's scene presence. | 442 | /// At the point of firing, the scene still contains the client's scene presence. |
443 | /// | ||
444 | /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please | ||
445 | /// do this on a separate thread. | ||
432 | /// </remarks> | 446 | /// </remarks> |
433 | public event ClientClosed OnClientClosed; | 447 | public event ClientClosed OnClientClosed; |
434 | 448 | ||
@@ -917,7 +931,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
917 | public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; | 931 | public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; |
918 | public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); | 932 | public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); |
919 | 933 | ||
920 | public delegate void SceneObjectPartUpdated(SceneObjectPart sop); | 934 | public delegate void SceneObjectPartUpdated(SceneObjectPart sop, bool full); |
921 | public event SceneObjectPartUpdated OnSceneObjectPartUpdated; | 935 | public event SceneObjectPartUpdated OnSceneObjectPartUpdated; |
922 | 936 | ||
923 | public delegate void ScenePresenceUpdated(ScenePresence sp); | 937 | public delegate void ScenePresenceUpdated(ScenePresence sp); |
@@ -2862,7 +2876,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2862 | } | 2876 | } |
2863 | } | 2877 | } |
2864 | 2878 | ||
2865 | public void TriggerSceneObjectPartUpdated(SceneObjectPart sop) | 2879 | public void TriggerSceneObjectPartUpdated(SceneObjectPart sop, bool full) |
2866 | { | 2880 | { |
2867 | SceneObjectPartUpdated handler = OnSceneObjectPartUpdated; | 2881 | SceneObjectPartUpdated handler = OnSceneObjectPartUpdated; |
2868 | if (handler != null) | 2882 | if (handler != null) |
@@ -2871,7 +2885,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2871 | { | 2885 | { |
2872 | try | 2886 | try |
2873 | { | 2887 | { |
2874 | d(sop); | 2888 | d(sop, full); |
2875 | } | 2889 | } |
2876 | catch (Exception e) | 2890 | catch (Exception e) |
2877 | { | 2891 | { |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 8d112db..c8e7156 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -80,6 +80,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
80 | public SynchronizeSceneHandler SynchronizeScene; | 80 | public SynchronizeSceneHandler SynchronizeScene; |
81 | 81 | ||
82 | /// <summary> | 82 | /// <summary> |
83 | /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. | ||
84 | /// </summary> | ||
85 | private object m_removeClientLock = new object(); | ||
86 | |||
87 | /// <summary> | ||
83 | /// Statistical information for this scene. | 88 | /// Statistical information for this scene. |
84 | /// </summary> | 89 | /// </summary> |
85 | public SimStatsReporter StatsReporter { get; private set; } | 90 | public SimStatsReporter StatsReporter { get; private set; } |
@@ -308,6 +313,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
308 | } | 313 | } |
309 | private volatile bool m_shuttingDown; | 314 | private volatile bool m_shuttingDown; |
310 | 315 | ||
316 | /// <summary> | ||
317 | /// Is the scene active? | ||
318 | /// </summary> | ||
319 | /// <remarks> | ||
320 | /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if | ||
321 | /// the scene is not active. | ||
322 | /// </remarks> | ||
323 | public bool Active | ||
324 | { | ||
325 | get { return m_active; } | ||
326 | set | ||
327 | { | ||
328 | if (value) | ||
329 | { | ||
330 | if (!m_active) | ||
331 | Start(); | ||
332 | } | ||
333 | else | ||
334 | { | ||
335 | m_active = false; | ||
336 | } | ||
337 | } | ||
338 | } | ||
339 | private volatile bool m_active; | ||
340 | |||
311 | // private int m_lastUpdate; | 341 | // private int m_lastUpdate; |
312 | private bool m_firstHeartbeat = true; | 342 | private bool m_firstHeartbeat = true; |
313 | 343 | ||
@@ -1187,6 +1217,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1187 | 1217 | ||
1188 | public void SetSceneCoreDebug(Dictionary<string, string> options) | 1218 | public void SetSceneCoreDebug(Dictionary<string, string> options) |
1189 | { | 1219 | { |
1220 | if (options.ContainsKey("active")) | ||
1221 | { | ||
1222 | bool active; | ||
1223 | |||
1224 | if (bool.TryParse(options["active"], out active)) | ||
1225 | Active = active; | ||
1226 | } | ||
1227 | |||
1190 | if (options.ContainsKey("scripting")) | 1228 | if (options.ContainsKey("scripting")) |
1191 | { | 1229 | { |
1192 | bool enableScripts = true; | 1230 | bool enableScripts = true; |
@@ -1326,6 +1364,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1326 | /// </summary> | 1364 | /// </summary> |
1327 | public void Start() | 1365 | public void Start() |
1328 | { | 1366 | { |
1367 | m_active = true; | ||
1368 | |||
1329 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); | 1369 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); |
1330 | 1370 | ||
1331 | //m_heartbeatTimer.Enabled = true; | 1371 | //m_heartbeatTimer.Enabled = true; |
@@ -1382,7 +1422,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1382 | #region Update Methods | 1422 | #region Update Methods |
1383 | 1423 | ||
1384 | /// <summary> | 1424 | /// <summary> |
1385 | /// Performs per-frame updates regularly | 1425 | /// Activate the various loops necessary to continually update the scene. |
1386 | /// </summary> | 1426 | /// </summary> |
1387 | private void Heartbeat() | 1427 | private void Heartbeat() |
1388 | { | 1428 | { |
@@ -1439,7 +1479,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1439 | List<Vector3> coarseLocations; | 1479 | List<Vector3> coarseLocations; |
1440 | List<UUID> avatarUUIDs; | 1480 | List<UUID> avatarUUIDs; |
1441 | 1481 | ||
1442 | while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) | 1482 | while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) |
1443 | { | 1483 | { |
1444 | runtc = Util.EnvironmentTickCount(); | 1484 | runtc = Util.EnvironmentTickCount(); |
1445 | ++MaintenanceRun; | 1485 | ++MaintenanceRun; |
@@ -1501,7 +1541,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1501 | int sleepMS; | 1541 | int sleepMS; |
1502 | int framestart; | 1542 | int framestart; |
1503 | 1543 | ||
1504 | while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) | 1544 | while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) |
1505 | { | 1545 | { |
1506 | framestart = Util.EnvironmentTickCount(); | 1546 | framestart = Util.EnvironmentTickCount(); |
1507 | ++Frame; | 1547 | ++Frame; |
@@ -2218,10 +2258,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2218 | public bool AddRestoredSceneObject( | 2258 | public bool AddRestoredSceneObject( |
2219 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 2259 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
2220 | { | 2260 | { |
2221 | bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); | 2261 | if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) |
2222 | if (result) | 2262 | { |
2223 | sceneObject.IsDeleted = false; | 2263 | sceneObject.IsDeleted = false; |
2224 | return result; | 2264 | EventManager.TriggerObjectAddedToScene(sceneObject); |
2265 | return true; | ||
2266 | } | ||
2267 | |||
2268 | return false; | ||
2225 | } | 2269 | } |
2226 | 2270 | ||
2227 | /// <summary> | 2271 | /// <summary> |
@@ -2862,77 +2906,89 @@ namespace OpenSim.Region.Framework.Scenes | |||
2862 | 2906 | ||
2863 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) | 2907 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) |
2864 | { | 2908 | { |
2909 | ScenePresence sp; | ||
2910 | bool vialogin; | ||
2911 | |||
2865 | // Validation occurs in LLUDPServer | 2912 | // Validation occurs in LLUDPServer |
2913 | // | ||
2914 | // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with | ||
2915 | // each other. In practice, this does not currently occur in the code. | ||
2866 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); | 2916 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); |
2867 | 2917 | ||
2868 | bool vialogin | 2918 | // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection |
2869 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 | 2919 | // and a simultaneous one that removes it (as can happen if the client is closed at a particular point |
2870 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; | 2920 | // whilst connecting). |
2871 | 2921 | // | |
2872 | CheckHeartbeat(); | 2922 | // It would be easier to lock across all NewUserConnection(), AddNewClient() and |
2873 | 2923 | // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service | |
2874 | ScenePresence sp = GetScenePresence(client.AgentId); | 2924 | // response in some module listening to AddNewClient()) from holding up unrelated agent calls. |
2875 | 2925 | // | |
2876 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this | 2926 | // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all |
2877 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause | 2927 | // AddNewClient() operations (though not other ops). |
2878 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already | 2928 | // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. |
2879 | // connected. | 2929 | lock (aCircuit) |
2880 | if (sp == null) | 2930 | { |
2881 | { | 2931 | vialogin |
2882 | m_log.DebugFormat( | 2932 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 |
2883 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", | 2933 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; |
2884 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); | 2934 | |
2885 | 2935 | CheckHeartbeat(); | |
2886 | m_clientManager.Add(client); | 2936 | |
2887 | SubscribeToClientEvents(client); | 2937 | sp = GetScenePresence(client.AgentId); |
2888 | |||
2889 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); | ||
2890 | m_eventManager.TriggerOnNewPresence(sp); | ||
2891 | |||
2892 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; | ||
2893 | 2938 | ||
2894 | // The first agent upon login is a root agent by design. | 2939 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this |
2895 | // For this agent we will have to rez the attachments. | 2940 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause |
2896 | // All other AddNewClient calls find aCircuit.child to be true. | 2941 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already |
2897 | if (aCircuit.child == false) | 2942 | // connected. |
2943 | if (sp == null) | ||
2898 | { | 2944 | { |
2899 | // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to | 2945 | m_log.DebugFormat( |
2900 | // start the scripts again (since this is done in RezAttachments()). | 2946 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", |
2901 | // XXX: This is convoluted. | 2947 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); |
2902 | sp.IsChildAgent = false; | 2948 | |
2903 | 2949 | m_clientManager.Add(client); | |
2904 | if (AttachmentsModule != null) | 2950 | SubscribeToClientEvents(client); |
2905 | Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); | 2951 | |
2952 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); | ||
2953 | m_eventManager.TriggerOnNewPresence(sp); | ||
2954 | |||
2955 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; | ||
2956 | |||
2957 | // The first agent upon login is a root agent by design. | ||
2958 | // For this agent we will have to rez the attachments. | ||
2959 | // All other AddNewClient calls find aCircuit.child to be true. | ||
2960 | if (aCircuit.child == false) | ||
2961 | { | ||
2962 | // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to | ||
2963 | // start the scripts again (since this is done in RezAttachments()). | ||
2964 | // XXX: This is convoluted. | ||
2965 | sp.IsChildAgent = false; | ||
2966 | |||
2967 | if (AttachmentsModule != null) | ||
2968 | Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); | ||
2969 | } | ||
2906 | } | 2970 | } |
2907 | } | 2971 | else |
2908 | else | 2972 | { |
2909 | { | 2973 | m_log.WarnFormat( |
2910 | m_log.WarnFormat( | 2974 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", |
2911 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", | 2975 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); |
2912 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); | 2976 | } |
2913 | } | 2977 | |
2978 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | ||
2979 | // client is for a root or child agent. | ||
2980 | client.SceneAgent = sp; | ||
2914 | 2981 | ||
2915 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | 2982 | // Cache the user's name |
2916 | // client is for a root or child agent. | 2983 | CacheUserName(sp, aCircuit); |
2917 | client.SceneAgent = sp; | 2984 | |
2985 | EventManager.TriggerOnNewClient(client); | ||
2986 | if (vialogin) | ||
2987 | EventManager.TriggerOnClientLogin(client); | ||
2988 | } | ||
2918 | 2989 | ||
2919 | m_LastLogin = Util.EnvironmentTickCount(); | 2990 | m_LastLogin = Util.EnvironmentTickCount(); |
2920 | 2991 | ||
2921 | // Cache the user's name | ||
2922 | CacheUserName(sp, aCircuit); | ||
2923 | |||
2924 | EventManager.TriggerOnNewClient(client); | ||
2925 | if (vialogin) | ||
2926 | { | ||
2927 | EventManager.TriggerOnClientLogin(client); | ||
2928 | // Send initial parcel data | ||
2929 | /* this is done on TriggerOnNewClient by landmanegement respective event handler | ||
2930 | Vector3 pos = sp.AbsolutePosition; | ||
2931 | ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y); | ||
2932 | land.SendLandUpdateToClient(client); | ||
2933 | */ | ||
2934 | } | ||
2935 | |||
2936 | return sp; | 2992 | return sp; |
2937 | } | 2993 | } |
2938 | 2994 | ||
@@ -3472,110 +3528,130 @@ namespace OpenSim.Region.Framework.Scenes | |||
3472 | { | 3528 | { |
3473 | // CheckHeartbeat(); | 3529 | // CheckHeartbeat(); |
3474 | bool isChildAgent = false; | 3530 | bool isChildAgent = false; |
3475 | ScenePresence avatar = GetScenePresence(agentID); | 3531 | AgentCircuitData acd; |
3476 | |||
3477 | if (avatar == null) | ||
3478 | { | ||
3479 | m_log.WarnFormat( | ||
3480 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); | ||
3481 | 3532 | ||
3482 | return; | 3533 | lock (m_removeClientLock) |
3483 | } | ||
3484 | |||
3485 | try | ||
3486 | { | 3534 | { |
3487 | isChildAgent = avatar.IsChildAgent; | 3535 | acd = m_authenticateHandler.GetAgentCircuitData(agentID); |
3488 | 3536 | ||
3489 | m_log.DebugFormat( | 3537 | if (acd == null) |
3490 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | ||
3491 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | ||
3492 | |||
3493 | // Don't do this to root agents, it's not nice for the viewer | ||
3494 | if (closeChildAgents && isChildAgent) | ||
3495 | { | 3538 | { |
3496 | // Tell a single agent to disconnect from the region. | 3539 | m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); |
3497 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | 3540 | return; |
3498 | if (eq != null) | ||
3499 | { | ||
3500 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3501 | } | ||
3502 | else | ||
3503 | { | ||
3504 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3505 | } | ||
3506 | } | 3541 | } |
3507 | 3542 | else | |
3508 | // Only applies to root agents. | ||
3509 | if (avatar.ParentID != 0) | ||
3510 | { | 3543 | { |
3511 | avatar.StandUp(); | 3544 | // We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred |
3545 | // simultaneously. | ||
3546 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); | ||
3512 | } | 3547 | } |
3548 | } | ||
3513 | 3549 | ||
3514 | m_sceneGraph.removeUserCount(!isChildAgent); | 3550 | lock (acd) |
3515 | 3551 | { | |
3516 | // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop | 3552 | ScenePresence avatar = GetScenePresence(agentID); |
3517 | // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI | 3553 | |
3518 | if (closeChildAgents && CapsModule != null) | 3554 | if (avatar == null) |
3519 | CapsModule.RemoveCaps(agentID); | ||
3520 | |||
3521 | // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | ||
3522 | // this method is doing is HORRIBLE!!! | ||
3523 | avatar.Scene.NeedSceneCacheClear(avatar.UUID); | ||
3524 | |||
3525 | if (closeChildAgents && !isChildAgent) | ||
3526 | { | 3555 | { |
3527 | List<ulong> regions = avatar.KnownRegionHandles; | 3556 | m_log.WarnFormat( |
3528 | regions.Remove(RegionInfo.RegionHandle); | 3557 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); |
3529 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | 3558 | |
3559 | return; | ||
3530 | } | 3560 | } |
3531 | 3561 | ||
3532 | m_eventManager.TriggerClientClosed(agentID, this); | 3562 | try |
3533 | m_eventManager.TriggerOnRemovePresence(agentID); | ||
3534 | |||
3535 | if (!isChildAgent) | ||
3536 | { | 3563 | { |
3537 | if (AttachmentsModule != null) | 3564 | isChildAgent = avatar.IsChildAgent; |
3565 | |||
3566 | m_log.DebugFormat( | ||
3567 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | ||
3568 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | ||
3569 | |||
3570 | // Don't do this to root agents, it's not nice for the viewer | ||
3571 | if (closeChildAgents && isChildAgent) | ||
3538 | { | 3572 | { |
3539 | AttachmentsModule.DeRezAttachments(avatar); | 3573 | // Tell a single agent to disconnect from the region. |
3574 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | ||
3575 | if (eq != null) | ||
3576 | { | ||
3577 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3578 | } | ||
3579 | else | ||
3580 | { | ||
3581 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3582 | } | ||
3540 | } | 3583 | } |
3541 | 3584 | ||
3542 | ForEachClient( | 3585 | // Only applies to root agents. |
3543 | delegate(IClientAPI client) | 3586 | if (avatar.ParentID != 0) |
3587 | { | ||
3588 | avatar.StandUp(); | ||
3589 | } | ||
3590 | |||
3591 | m_sceneGraph.removeUserCount(!isChildAgent); | ||
3592 | |||
3593 | // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop | ||
3594 | // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI | ||
3595 | if (closeChildAgents && CapsModule != null) | ||
3596 | CapsModule.RemoveCaps(agentID); | ||
3597 | |||
3598 | // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | ||
3599 | // this method is doing is HORRIBLE!!! | ||
3600 | avatar.Scene.NeedSceneCacheClear(avatar.UUID); | ||
3601 | |||
3602 | if (closeChildAgents && !isChildAgent) | ||
3603 | { | ||
3604 | List<ulong> regions = avatar.KnownRegionHandles; | ||
3605 | regions.Remove(RegionInfo.RegionHandle); | ||
3606 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | ||
3607 | } | ||
3608 | |||
3609 | m_eventManager.TriggerClientClosed(agentID, this); | ||
3610 | m_eventManager.TriggerOnRemovePresence(agentID); | ||
3611 | |||
3612 | if (!isChildAgent) | ||
3613 | { | ||
3614 | if (AttachmentsModule != null) | ||
3544 | { | 3615 | { |
3545 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway | 3616 | AttachmentsModule.DeRezAttachments(avatar); |
3546 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } | 3617 | } |
3547 | catch (NullReferenceException) { } | ||
3548 | }); | ||
3549 | } | ||
3550 | |||
3551 | // It's possible for child agents to have transactions if changes are being made cross-border. | ||
3552 | if (AgentTransactionsModule != null) | ||
3553 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | ||
3554 | 3618 | ||
3555 | m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); | 3619 | ForEachClient( |
3556 | m_log.Debug("[Scene] The avatar has left the building"); | 3620 | delegate(IClientAPI client) |
3557 | } | 3621 | { |
3558 | catch (Exception e) | 3622 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway |
3559 | { | 3623 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } |
3560 | m_log.Error( | 3624 | catch (NullReferenceException) { } |
3561 | string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); | 3625 | }); |
3562 | } | 3626 | } |
3563 | finally | ||
3564 | { | ||
3565 | try | ||
3566 | { | ||
3567 | // Always clean these structures up so that any failure above doesn't cause them to remain in the | ||
3568 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering | ||
3569 | // the same cleanup exception continually. | ||
3570 | m_sceneGraph.RemoveScenePresence(agentID); | ||
3571 | m_clientManager.Remove(agentID); | ||
3572 | 3627 | ||
3573 | avatar.Close(); | 3628 | // It's possible for child agents to have transactions if changes are being made cross-border. |
3629 | if (AgentTransactionsModule != null) | ||
3630 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | ||
3631 | m_log.Debug("[Scene] The avatar has left the building"); | ||
3574 | } | 3632 | } |
3575 | catch (Exception e) | 3633 | catch (Exception e) |
3576 | { | 3634 | { |
3577 | m_log.Error( | 3635 | m_log.Error( |
3578 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); | 3636 | string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); |
3637 | } | ||
3638 | finally | ||
3639 | { | ||
3640 | try | ||
3641 | { | ||
3642 | // Always clean these structures up so that any failure above doesn't cause them to remain in the | ||
3643 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering | ||
3644 | // the same cleanup exception continually. | ||
3645 | m_sceneGraph.RemoveScenePresence(agentID); | ||
3646 | m_clientManager.Remove(agentID); | ||
3647 | |||
3648 | avatar.Close(); | ||
3649 | } | ||
3650 | catch (Exception e) | ||
3651 | { | ||
3652 | m_log.Error( | ||
3653 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); | ||
3654 | } | ||
3579 | } | 3655 | } |
3580 | } | 3656 | } |
3581 | 3657 | ||
@@ -3634,11 +3710,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3634 | 3710 | ||
3635 | /// <summary> | 3711 | /// <summary> |
3636 | /// Do the work necessary to initiate a new user connection for a particular scene. | 3712 | /// Do the work necessary to initiate a new user connection for a particular scene. |
3637 | /// At the moment, this consists of setting up the caps infrastructure | ||
3638 | /// The return bool should allow for connections to be refused, but as not all calling paths | ||
3639 | /// take proper notice of it let, we allowed banned users in still. | ||
3640 | /// </summary> | 3713 | /// </summary> |
3641 | /// <param name="agent">CircuitData of the agent who is connecting</param> | 3714 | /// <param name="agent">CircuitData of the agent who is connecting</param> |
3715 | /// <param name="teleportFlags"></param> | ||
3642 | /// <param name="reason">Outputs the reason for the false response on this string</param> | 3716 | /// <param name="reason">Outputs the reason for the false response on this string</param> |
3643 | /// <returns>True if the region accepts this agent. False if it does not. False will | 3717 | /// <returns>True if the region accepts this agent. False if it does not. False will |
3644 | /// also return a reason.</returns> | 3718 | /// also return a reason.</returns> |
@@ -3649,10 +3723,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
3649 | 3723 | ||
3650 | /// <summary> | 3724 | /// <summary> |
3651 | /// Do the work necessary to initiate a new user connection for a particular scene. | 3725 | /// Do the work necessary to initiate a new user connection for a particular scene. |
3652 | /// At the moment, this consists of setting up the caps infrastructure | 3726 | /// </summary> |
3727 | /// <remarks> | ||
3728 | /// The return bool should allow for connections to be refused, but as not all calling paths | ||
3729 | /// take proper notice of it yet, we still allowed banned users in. | ||
3730 | /// | ||
3731 | /// At the moment this method consists of setting up the caps infrastructure | ||
3653 | /// The return bool should allow for connections to be refused, but as not all calling paths | 3732 | /// The return bool should allow for connections to be refused, but as not all calling paths |
3654 | /// take proper notice of it let, we allowed banned users in still. | 3733 | /// take proper notice of it let, we allowed banned users in still. |
3655 | /// </summary> | 3734 | /// |
3735 | /// This method is called by the login service (in the case of login) or another simulator (in the case of region | ||
3736 | /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection | ||
3737 | /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of | ||
3738 | /// the LLUDP stack). | ||
3739 | /// </remarks> | ||
3656 | /// <param name="agent">CircuitData of the agent who is connecting</param> | 3740 | /// <param name="agent">CircuitData of the agent who is connecting</param> |
3657 | /// <param name="reason">Outputs the reason for the false response on this string</param> | 3741 | /// <param name="reason">Outputs the reason for the false response on this string</param> |
3658 | /// <param name="requirePresenceLookup">True for normal presence. False for NPC | 3742 | /// <param name="requirePresenceLookup">True for normal presence. False for NPC |
@@ -3755,79 +3839,82 @@ namespace OpenSim.Region.Framework.Scenes | |||
3755 | sp = null; | 3839 | sp = null; |
3756 | } | 3840 | } |
3757 | 3841 | ||
3758 | 3842 | lock (agent) | |
3759 | //On login test land permisions | ||
3760 | if (vialogin) | ||
3761 | { | 3843 | { |
3762 | IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); | 3844 | //On login test land permisions |
3763 | if (cache != null) | 3845 | if (vialogin) |
3764 | cache.Remove(agent.firstname + " " + agent.lastname); | ||
3765 | if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) | ||
3766 | { | 3846 | { |
3767 | m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); | 3847 | IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); |
3768 | return false; | 3848 | if (cache != null) |
3849 | cache.Remove(agent.firstname + " " + agent.lastname); | ||
3850 | if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) | ||
3851 | { | ||
3852 | m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); | ||
3853 | return false; | ||
3854 | } | ||
3769 | } | 3855 | } |
3770 | } | ||
3771 | 3856 | ||
3772 | if (sp == null) // We don't have an [child] agent here already | 3857 | if (sp == null) // We don't have an [child] agent here already |
3773 | { | ||
3774 | if (requirePresenceLookup) | ||
3775 | { | 3858 | { |
3776 | try | 3859 | if (requirePresenceLookup) |
3777 | { | 3860 | { |
3778 | if (!VerifyUserPresence(agent, out reason)) | 3861 | try |
3862 | { | ||
3863 | if (!VerifyUserPresence(agent, out reason)) | ||
3864 | return false; | ||
3865 | } catch (Exception e) | ||
3866 | { | ||
3867 | m_log.ErrorFormat( | ||
3868 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | ||
3779 | return false; | 3869 | return false; |
3780 | } catch (Exception e) | 3870 | } |
3871 | } | ||
3872 | |||
3873 | try | ||
3874 | { | ||
3875 | // Always check estate if this is a login. Always | ||
3876 | // check if banned regions are to be blacked out. | ||
3877 | if (vialogin || (!m_seeIntoBannedRegion)) | ||
3878 | { | ||
3879 | if (!AuthorizeUser(agent, out reason)) | ||
3880 | return false; | ||
3881 | } | ||
3882 | } | ||
3883 | catch (Exception e) | ||
3781 | { | 3884 | { |
3782 | m_log.ErrorFormat( | 3885 | m_log.ErrorFormat( |
3783 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | 3886 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); |
3784 | return false; | 3887 | return false; |
3785 | } | 3888 | } |
3786 | } | ||
3787 | 3889 | ||
3788 | try | 3890 | m_log.InfoFormat( |
3789 | { | 3891 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", |
3790 | // Always check estate if this is a login. Always | 3892 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, |
3791 | // check if banned regions are to be blacked out. | 3893 | agent.AgentID, agent.circuitcode); |
3792 | if (vialogin || (!m_seeIntoBannedRegion)) | 3894 | |
3895 | if (CapsModule != null) | ||
3793 | { | 3896 | { |
3794 | if (!AuthorizeUser(agent, out reason)) | 3897 | CapsModule.SetAgentCapsSeeds(agent); |
3795 | return false; | 3898 | CapsModule.CreateCaps(agent.AgentID); |
3796 | } | 3899 | } |
3797 | } | 3900 | } |
3798 | catch (Exception e) | 3901 | else |
3799 | { | 3902 | { |
3800 | m_log.ErrorFormat( | 3903 | // Let the SP know how we got here. This has a lot of interesting |
3801 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); | 3904 | // uses down the line. |
3802 | return false; | 3905 | sp.TeleportFlags = (TPFlags)teleportFlags; |
3803 | } | ||
3804 | |||
3805 | m_log.InfoFormat( | ||
3806 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", | ||
3807 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, | ||
3808 | agent.AgentID, agent.circuitcode); | ||
3809 | 3906 | ||
3810 | if (CapsModule != null) | 3907 | if (sp.IsChildAgent) |
3811 | { | 3908 | { |
3812 | CapsModule.SetAgentCapsSeeds(agent); | 3909 | m_log.DebugFormat( |
3813 | CapsModule.CreateCaps(agent.AgentID); | 3910 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", |
3814 | } | 3911 | agent.AgentID, RegionInfo.RegionName); |
3815 | } else | ||
3816 | { | ||
3817 | // Let the SP know how we got here. This has a lot of interesting | ||
3818 | // uses down the line. | ||
3819 | sp.TeleportFlags = (TPFlags)teleportFlags; | ||
3820 | 3912 | ||
3821 | if (sp.IsChildAgent) | 3913 | sp.AdjustKnownSeeds(); |
3822 | { | ||
3823 | m_log.DebugFormat( | ||
3824 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", | ||
3825 | agent.AgentID, RegionInfo.RegionName); | ||
3826 | 3914 | ||
3827 | sp.AdjustKnownSeeds(); | 3915 | if (CapsModule != null) |
3828 | 3916 | CapsModule.SetAgentCapsSeeds(agent); | |
3829 | if (CapsModule != null) | 3917 | } |
3830 | CapsModule.SetAgentCapsSeeds(agent); | ||
3831 | } | 3918 | } |
3832 | } | 3919 | } |
3833 | 3920 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index a31a9ea..d5d8f26 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -3082,7 +3082,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3082 | // UUID, Name, TimeStampFull); | 3082 | // UUID, Name, TimeStampFull); |
3083 | 3083 | ||
3084 | if (ParentGroup.Scene != null) | 3084 | if (ParentGroup.Scene != null) |
3085 | ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); | 3085 | ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); |
3086 | } | 3086 | } |
3087 | 3087 | ||
3088 | /// <summary> | 3088 | /// <summary> |
@@ -3116,7 +3116,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3116 | } | 3116 | } |
3117 | 3117 | ||
3118 | if (ParentGroup.Scene != null) | 3118 | if (ParentGroup.Scene != null) |
3119 | ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); | 3119 | ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false); |
3120 | } | 3120 | } |
3121 | 3121 | ||
3122 | public void ScriptSetPhysicsStatus(bool UsePhysics) | 3122 | public void ScriptSetPhysicsStatus(bool UsePhysics) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a52e01..2e6b2da 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -263,7 +263,7 @@ public class BSCharacter : BSPhysObject | |||
263 | // A version of the sanity check that also makes sure a new position value is | 263 | // A version of the sanity check that also makes sure a new position value is |
264 | // pushed back to the physics engine. This routine would be used by anyone | 264 | // pushed back to the physics engine. This routine would be used by anyone |
265 | // who is not already pushing the value. | 265 | // who is not already pushing the value. |
266 | private bool PositionSanityCheck2(bool atTaintTime) | 266 | private bool PositionSanityCheck2(bool inTaintTime) |
267 | { | 267 | { |
268 | bool ret = false; | 268 | bool ret = false; |
269 | if (PositionSanityCheck()) | 269 | if (PositionSanityCheck()) |
@@ -275,7 +275,7 @@ public class BSCharacter : BSPhysObject | |||
275 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 275 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
276 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); | 276 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); |
277 | }; | 277 | }; |
278 | if (atTaintTime) | 278 | if (inTaintTime) |
279 | sanityOperation(); | 279 | sanityOperation(); |
280 | else | 280 | else |
281 | PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); | 281 | PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); |
@@ -332,6 +332,13 @@ public class BSCharacter : BSPhysObject | |||
332 | }); | 332 | }); |
333 | } | 333 | } |
334 | } | 334 | } |
335 | public override OMV.Vector3 ForceVelocity { | ||
336 | get { return _velocity; } | ||
337 | set { | ||
338 | _velocity = value; | ||
339 | BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); | ||
340 | } | ||
341 | } | ||
335 | public override OMV.Vector3 Torque { | 342 | public override OMV.Vector3 Torque { |
336 | get { return _torque; } | 343 | get { return _torque; } |
337 | set { _torque = value; | 344 | set { _torque = value; |
@@ -432,6 +439,10 @@ public class BSCharacter : BSPhysObject | |||
432 | get { return _rotationalVelocity; } | 439 | get { return _rotationalVelocity; } |
433 | set { _rotationalVelocity = value; } | 440 | set { _rotationalVelocity = value; } |
434 | } | 441 | } |
442 | public override OMV.Vector3 ForceRotationalVelocity { | ||
443 | get { return _rotationalVelocity; } | ||
444 | set { _rotationalVelocity = value; } | ||
445 | } | ||
435 | public override bool Kinematic { | 446 | public override bool Kinematic { |
436 | get { return _kinematic; } | 447 | get { return _kinematic; } |
437 | set { _kinematic = value; } | 448 | set { _kinematic = value; } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 63a4127..a20be3a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | |||
@@ -49,9 +49,16 @@ public abstract class BSConstraint : IDisposable | |||
49 | if (m_enabled) | 49 | if (m_enabled) |
50 | { | 50 | { |
51 | m_enabled = false; | 51 | m_enabled = false; |
52 | bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); | 52 | if (m_constraint.ptr != IntPtr.Zero) |
53 | m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); | 53 | { |
54 | m_constraint.ptr = System.IntPtr.Zero; | 54 | bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); |
55 | m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", | ||
56 | BSScene.DetailLogZero, | ||
57 | m_body1.ID, m_body1.ptr.ToString("X"), | ||
58 | m_body2.ID, m_body2.ptr.ToString("X"), | ||
59 | success); | ||
60 | m_constraint.ptr = System.IntPtr.Zero; | ||
61 | } | ||
55 | } | 62 | } |
56 | } | 63 | } |
57 | 64 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 4ba2f62..56342b8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -462,7 +462,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
462 | return; | 462 | return; |
463 | 463 | ||
464 | // Set the prim's inertia to zero. The vehicle code handles that and this | 464 | // Set the prim's inertia to zero. The vehicle code handles that and this |
465 | // removes the torque action introduced by Bullet. | 465 | // removes the motion and torque actions introduced by Bullet. |
466 | Vector3 inertia = Vector3.Zero; | 466 | Vector3 inertia = Vector3.Zero; |
467 | BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); | 467 | BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); |
468 | BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); | 468 | BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); |
@@ -481,7 +481,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
481 | m_lastPositionVector = Prim.ForcePosition; | 481 | m_lastPositionVector = Prim.ForcePosition; |
482 | 482 | ||
483 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", | 483 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", |
484 | Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity); | 484 | Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); |
485 | }// end Step | 485 | }// end Step |
486 | 486 | ||
487 | // Apply the effect of the linear motor. | 487 | // Apply the effect of the linear motor. |
@@ -540,7 +540,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
540 | // add Gravity and Buoyancy | 540 | // add Gravity and Buoyancy |
541 | // There is some gravity, make a gravity force vector that is applied after object velocity. | 541 | // There is some gravity, make a gravity force vector that is applied after object velocity. |
542 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | 542 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; |
543 | Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Mass * (1f - m_VehicleBuoyancy)); | 543 | Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy)); |
544 | 544 | ||
545 | /* | 545 | /* |
546 | * RA: Not sure why one would do this | 546 | * RA: Not sure why one would do this |
@@ -678,10 +678,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
678 | m_newVelocity.Z = 0; | 678 | m_newVelocity.Z = 0; |
679 | 679 | ||
680 | // Apply velocity | 680 | // Apply velocity |
681 | Prim.Velocity = m_newVelocity; | 681 | Prim.ForceVelocity = m_newVelocity; |
682 | // apply gravity force | 682 | // apply gravity force |
683 | // Why is this set here? The physics engine already does gravity. | 683 | // Why is this set here? The physics engine already does gravity. |
684 | // m_prim.AddForce(grav, false); | 684 | Prim.AddForce(grav, false, true); |
685 | 685 | ||
686 | // Apply friction | 686 | // Apply friction |
687 | Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); | 687 | Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); |
@@ -704,7 +704,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
704 | // m_lastAngularVelocity // what was last applied to body | 704 | // m_lastAngularVelocity // what was last applied to body |
705 | 705 | ||
706 | // Get what the body is doing, this includes 'external' influences | 706 | // Get what the body is doing, this includes 'external' influences |
707 | Vector3 angularVelocity = Prim.RotationalVelocity; | 707 | Vector3 angularVelocity = Prim.ForceRotationalVelocity; |
708 | 708 | ||
709 | if (m_angularMotorApply > 0) | 709 | if (m_angularMotorApply > 0) |
710 | { | 710 | { |
@@ -810,7 +810,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
810 | m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; | 810 | m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; |
811 | 811 | ||
812 | // Apply to the body | 812 | // Apply to the body |
813 | Prim.RotationalVelocity = m_lastAngularVelocity; | 813 | Prim.ForceRotationalVelocity = m_lastAngularVelocity; |
814 | 814 | ||
815 | VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); | 815 | VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); |
816 | } //end MoveAngular | 816 | } //end MoveAngular |
@@ -862,7 +862,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
862 | private void VDetailLog(string msg, params Object[] args) | 862 | private void VDetailLog(string msg, params Object[] args) |
863 | { | 863 | { |
864 | if (Prim.PhysicsScene.VehicleLoggingEnabled) | 864 | if (Prim.PhysicsScene.VehicleLoggingEnabled) |
865 | Prim.PhysicsScene.PhysicsLogging.Write(msg, args); | 865 | Prim.PhysicsScene.DetailLog(msg, args); |
866 | } | 866 | } |
867 | } | 867 | } |
868 | } | 868 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3e82642..43b1262 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -52,8 +52,8 @@ public class BSLinkset | |||
52 | // the physical 'taint' children separately. | 52 | // the physical 'taint' children separately. |
53 | // After taint processing and before the simulation step, these | 53 | // After taint processing and before the simulation step, these |
54 | // two lists must be the same. | 54 | // two lists must be the same. |
55 | private List<BSPhysObject> m_children; | 55 | private HashSet<BSPhysObject> m_children; |
56 | private List<BSPhysObject> m_taintChildren; | 56 | private HashSet<BSPhysObject> m_taintChildren; |
57 | 57 | ||
58 | // We lock the diddling of linkset classes to prevent any badness. | 58 | // We lock the diddling of linkset classes to prevent any badness. |
59 | // This locks the modification of the instances of this class. Changes | 59 | // This locks the modification of the instances of this class. Changes |
@@ -90,8 +90,8 @@ public class BSLinkset | |||
90 | m_nextLinksetID = 1; | 90 | m_nextLinksetID = 1; |
91 | PhysicsScene = scene; | 91 | PhysicsScene = scene; |
92 | LinksetRoot = parent; | 92 | LinksetRoot = parent; |
93 | m_children = new List<BSPhysObject>(); | 93 | m_children = new HashSet<BSPhysObject>(); |
94 | m_taintChildren = new List<BSPhysObject>(); | 94 | m_taintChildren = new HashSet<BSPhysObject>(); |
95 | m_mass = parent.MassRaw; | 95 | m_mass = parent.MassRaw; |
96 | } | 96 | } |
97 | 97 | ||
@@ -160,6 +160,28 @@ public class BSLinkset | |||
160 | return ret; | 160 | return ret; |
161 | } | 161 | } |
162 | 162 | ||
163 | // When physical properties are changed the linkset needs to recalculate | ||
164 | // its internal properties. | ||
165 | // May be called at runtime or taint-time (just pass the appropriate flag). | ||
166 | public void Refresh(BSPhysObject requestor, bool inTaintTime) | ||
167 | { | ||
168 | // If there are no children, not physical or not root, I am not the one that recomputes the constraints | ||
169 | // (For the moment, static linksets do create constraints so remove the test for physical.) | ||
170 | if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor)) | ||
171 | return; | ||
172 | |||
173 | BSScene.TaintCallback refreshOperation = delegate() | ||
174 | { | ||
175 | RecomputeLinksetConstraintVariables(); | ||
176 | DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", | ||
177 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); | ||
178 | }; | ||
179 | if (inTaintTime) | ||
180 | refreshOperation(); | ||
181 | else | ||
182 | PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); | ||
183 | } | ||
184 | |||
163 | // The object is going dynamic (physical). Do any setup necessary | 185 | // The object is going dynamic (physical). Do any setup necessary |
164 | // for a dynamic linkset. | 186 | // for a dynamic linkset. |
165 | // Only the state of the passed object can be modified. The rest of the linkset | 187 | // Only the state of the passed object can be modified. The rest of the linkset |
@@ -182,22 +204,19 @@ public class BSLinkset | |||
182 | return false; | 204 | return false; |
183 | } | 205 | } |
184 | 206 | ||
185 | // When physical properties are changed the linkset needs to recalculate | 207 | // If the software is handling the movement of all the objects in a linkset |
186 | // its internal properties. | 208 | // (like if one doesn't use constraints for static linksets), this is called |
187 | // Called at runtime. | 209 | // when an update for the root of the linkset is received. |
188 | public void Refresh(BSPhysObject requestor) | 210 | // Called at taint-time!! |
211 | public void UpdateProperties(BSPhysObject physObject) | ||
189 | { | 212 | { |
190 | // If there are no children, there can't be any constraints to recompute | 213 | // The root local properties have been updated. Apply to the children if appropriate. |
191 | if (!HasAnyChildren) | 214 | if (IsRoot(physObject) && HasAnyChildren) |
192 | return; | ||
193 | |||
194 | // Only the root does the recomputation | ||
195 | if (IsRoot(requestor)) | ||
196 | { | 215 | { |
197 | PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() | 216 | if (!physObject.IsPhysical) |
198 | { | 217 | { |
199 | RecomputeLinksetConstraintVariables(); | 218 | // TODO: implement software linkset update for static object linksets |
200 | }); | 219 | } |
201 | } | 220 | } |
202 | } | 221 | } |
203 | 222 | ||
@@ -215,13 +234,10 @@ public class BSLinkset | |||
215 | if (IsRoot(child)) | 234 | if (IsRoot(child)) |
216 | { | 235 | { |
217 | // If the one with the dependency is root, must undo all children | 236 | // If the one with the dependency is root, must undo all children |
218 | DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", | 237 | DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", |
219 | child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); | 238 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); |
220 | foreach (BSPhysObject bpo in m_taintChildren) | 239 | |
221 | { | 240 | ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); |
222 | PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); | ||
223 | ret = true; | ||
224 | } | ||
225 | } | 241 | } |
226 | else | 242 | else |
227 | { | 243 | { |
@@ -229,20 +245,16 @@ public class BSLinkset | |||
229 | child.LocalID, | 245 | child.LocalID, |
230 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), | 246 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), |
231 | child.LocalID, child.BSBody.ptr.ToString("X")); | 247 | child.LocalID, child.BSBody.ptr.ToString("X")); |
232 | // Remove the dependency on the body of this one | 248 | // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); |
233 | if (m_taintChildren.Contains(child)) | 249 | // Despite the function name, this removes any link to the specified object. |
234 | { | 250 | ret = PhysicallyUnlinkAllChildrenFromRoot(child); |
235 | PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); | ||
236 | ret = true; | ||
237 | } | ||
238 | } | 251 | } |
239 | } | 252 | } |
240 | return ret; | 253 | return ret; |
241 | } | 254 | } |
242 | 255 | ||
243 | // Routine used when rebuilding the body of the root of the linkset | 256 | // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', |
244 | // This is called after RemoveAllLinksToRoot() to restore all the constraints. | 257 | // this routine will restore the removed constraints. |
245 | // This is called when the root body has been changed. | ||
246 | // Called at taint-time!! | 258 | // Called at taint-time!! |
247 | public void RestoreBodyDependencies(BSPrim child) | 259 | public void RestoreBodyDependencies(BSPrim child) |
248 | { | 260 | { |
@@ -254,7 +266,7 @@ public class BSLinkset | |||
254 | child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); | 266 | child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); |
255 | foreach (BSPhysObject bpo in m_taintChildren) | 267 | foreach (BSPhysObject bpo in m_taintChildren) |
256 | { | 268 | { |
257 | PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); | 269 | PhysicallyLinkAChildToRoot(LinksetRoot, bpo); |
258 | } | 270 | } |
259 | } | 271 | } |
260 | else | 272 | else |
@@ -263,7 +275,7 @@ public class BSLinkset | |||
263 | LinksetRoot.LocalID, | 275 | LinksetRoot.LocalID, |
264 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), | 276 | LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), |
265 | child.LocalID, child.BSBody.ptr.ToString("X")); | 277 | child.LocalID, child.BSBody.ptr.ToString("X")); |
266 | PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); | 278 | PhysicallyLinkAChildToRoot(LinksetRoot, child); |
267 | } | 279 | } |
268 | } | 280 | } |
269 | } | 281 | } |
@@ -330,22 +342,22 @@ public class BSLinkset | |||
330 | { | 342 | { |
331 | m_children.Add(child); | 343 | m_children.Add(child); |
332 | 344 | ||
333 | BSPhysObject rootx = LinksetRoot; // capture the root and body as of now | 345 | BSPhysObject rootx = LinksetRoot; // capture the root as of now |
334 | BSPhysObject childx = child; | 346 | BSPhysObject childx = child; |
335 | 347 | ||
336 | DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", | 348 | DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); |
337 | rootx.LocalID, | ||
338 | rootx.LocalID, rootx.BSBody.ptr.ToString("X"), | ||
339 | childx.LocalID, childx.BSBody.ptr.ToString("X")); | ||
340 | 349 | ||
341 | PhysicsScene.TaintedObject("AddChildToLinkset", delegate() | 350 | PhysicsScene.TaintedObject("AddChildToLinkset", delegate() |
342 | { | 351 | { |
343 | DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); | 352 | DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", |
344 | // build the physical binding between me and the child | 353 | rootx.LocalID, |
345 | m_taintChildren.Add(childx); | 354 | rootx.LocalID, rootx.BSBody.ptr.ToString("X"), |
346 | 355 | childx.LocalID, childx.BSBody.ptr.ToString("X")); | |
347 | // Since this is taint-time, the body and shape could have changed for the child | 356 | // Since this is taint-time, the body and shape could have changed for the child |
348 | PhysicallyLinkAChildToRoot(rootx, rootx.BSBody, childx, childx.BSBody); | 357 | rootx.ForcePosition = rootx.Position; // DEBUG |
358 | childx.ForcePosition = childx.Position; // DEBUG | ||
359 | PhysicallyLinkAChildToRoot(rootx, childx); | ||
360 | m_taintChildren.Add(child); | ||
349 | }); | 361 | }); |
350 | } | 362 | } |
351 | return; | 363 | return; |
@@ -378,10 +390,8 @@ public class BSLinkset | |||
378 | 390 | ||
379 | PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() | 391 | PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() |
380 | { | 392 | { |
381 | if (m_taintChildren.Contains(childx)) | 393 | m_taintChildren.Remove(child); |
382 | m_taintChildren.Remove(childx); | 394 | PhysicallyUnlinkAChildFromRoot(rootx, childx); |
383 | |||
384 | PhysicallyUnlinkAChildFromRoot(rootx, rootx.BSBody, childx, childx.BSBody); | ||
385 | RecomputeLinksetConstraintVariables(); | 395 | RecomputeLinksetConstraintVariables(); |
386 | }); | 396 | }); |
387 | 397 | ||
@@ -396,8 +406,7 @@ public class BSLinkset | |||
396 | 406 | ||
397 | // Create a constraint between me (root of linkset) and the passed prim (the child). | 407 | // Create a constraint between me (root of linkset) and the passed prim (the child). |
398 | // Called at taint time! | 408 | // Called at taint time! |
399 | private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody, | 409 | private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) |
400 | BSPhysObject childPrim, BulletBody childBody) | ||
401 | { | 410 | { |
402 | // Zero motion for children so they don't interpolate | 411 | // Zero motion for children so they don't interpolate |
403 | childPrim.ZeroMotion(); | 412 | childPrim.ZeroMotion(); |
@@ -409,33 +418,17 @@ public class BSLinkset | |||
409 | // real world coordinate of midpoint between the two objects | 418 | // real world coordinate of midpoint between the two objects |
410 | OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); | 419 | OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); |
411 | 420 | ||
412 | DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", | 421 | DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", |
413 | rootPrim.LocalID, | 422 | rootPrim.LocalID, |
414 | rootPrim.LocalID, rootBody.ptr.ToString("X"), | 423 | rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), |
415 | childPrim.LocalID, childBody.ptr.ToString("X"), | 424 | childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), |
416 | rootPrim.Position, childPrim.Position, midPoint); | 425 | rootPrim.Position, childPrim.Position, midPoint); |
417 | 426 | ||
418 | // create a constraint that allows no freedom of movement between the two objects | 427 | // create a constraint that allows no freedom of movement between the two objects |
419 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | 428 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 |
420 | 429 | ||
421 | // There is great subtlty in these paramters. Notice the check for a ptr of zero. | ||
422 | // We pass the BulletBody structure into the taint in order to capture the pointer | ||
423 | // of the body at the time of constraint creation. This doesn't work for the very first | ||
424 | // construction because there is no body yet. The body | ||
425 | // is constructed later at taint time. Thus we use the body address at time of the | ||
426 | // taint creation but, if it is zero, use what's in the prim at the moment. | ||
427 | // There is a possible race condition since shape can change without a taint call | ||
428 | // (like changing to a mesh that is already constructed). The fix for that would be | ||
429 | // to only change BSShape at taint time thus syncronizing these operations at | ||
430 | // the cost of efficiency and lag. | ||
431 | BS6DofConstraint constrain = new BS6DofConstraint( | 430 | BS6DofConstraint constrain = new BS6DofConstraint( |
432 | PhysicsScene.World, | 431 | PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); |
433 | rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody, | ||
434 | childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody, | ||
435 | midPoint, | ||
436 | true, | ||
437 | true | ||
438 | ); | ||
439 | 432 | ||
440 | /* NOTE: below is an attempt to build constraint with full frame computation, etc. | 433 | /* NOTE: below is an attempt to build constraint with full frame computation, etc. |
441 | * Using the midpoint is easier since it lets the Bullet code manipulate the transforms | 434 | * Using the midpoint is easier since it lets the Bullet code manipulate the transforms |
@@ -452,7 +445,7 @@ public class BSLinkset | |||
452 | 445 | ||
453 | // create a constraint that allows no freedom of movement between the two objects | 446 | // create a constraint that allows no freedom of movement between the two objects |
454 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | 447 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 |
455 | DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); | 448 | DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); |
456 | BS6DofConstraint constrain = new BS6DofConstraint( | 449 | BS6DofConstraint constrain = new BS6DofConstraint( |
457 | PhysicsScene.World, rootPrim.Body, childPrim.Body, | 450 | PhysicsScene.World, rootPrim.Body, childPrim.Body, |
458 | OMV.Vector3.Zero, | 451 | OMV.Vector3.Zero, |
@@ -486,39 +479,44 @@ public class BSLinkset | |||
486 | { | 479 | { |
487 | constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); | 480 | constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); |
488 | } | 481 | } |
489 | |||
490 | RecomputeLinksetConstraintVariables(); | ||
491 | } | 482 | } |
492 | 483 | ||
493 | // Remove linkage between myself and a particular child | 484 | // Remove linkage between myself and a particular child |
494 | // The root and child bodies are passed in because we need to remove the constraint between | 485 | // The root and child bodies are passed in because we need to remove the constraint between |
495 | // the bodies that were at unlink time. | 486 | // the bodies that were at unlink time. |
496 | // Called at taint time! | 487 | // Called at taint time! |
497 | private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody, | 488 | private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) |
498 | BSPhysObject childPrim, BulletBody childBody) | ||
499 | { | 489 | { |
500 | DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", | 490 | bool ret = false; |
491 | DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", | ||
501 | rootPrim.LocalID, | 492 | rootPrim.LocalID, |
502 | rootPrim.LocalID, rootBody.ptr.ToString("X"), | 493 | rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), |
503 | childPrim.LocalID, childBody.ptr.ToString("X")); | 494 | childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); |
504 | 495 | ||
505 | // Find the constraint for this link and get rid of it from the overall collection and from my list | 496 | // Find the constraint for this link and get rid of it from the overall collection and from my list |
506 | PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootBody, childBody); | 497 | if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) |
498 | { | ||
499 | // Make the child refresh its location | ||
500 | BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); | ||
501 | ret = true; | ||
502 | } | ||
507 | 503 | ||
508 | // Make the child refresh its location | 504 | return ret; |
509 | BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); | ||
510 | } | 505 | } |
511 | 506 | ||
512 | /* | ||
513 | // Remove linkage between myself and any possible children I might have. | 507 | // Remove linkage between myself and any possible children I might have. |
514 | // Called at taint time! | 508 | // Called at taint time! |
515 | private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) | 509 | private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) |
516 | { | 510 | { |
517 | DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); | 511 | DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); |
512 | bool ret = false; | ||
518 | 513 | ||
519 | PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); | 514 | if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) |
515 | { | ||
516 | ret = true; | ||
517 | } | ||
518 | return ret; | ||
520 | } | 519 | } |
521 | */ | ||
522 | 520 | ||
523 | // Call each of the constraints that make up this linkset and recompute the | 521 | // Call each of the constraints that make up this linkset and recompute the |
524 | // various transforms and variables. Used when objects are added or removed | 522 | // various transforms and variables. Used when objects are added or removed |
@@ -550,11 +548,17 @@ public class BSLinkset | |||
550 | { | 548 | { |
551 | // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass | 549 | // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass |
552 | OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); | 550 | OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); |
553 | BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); | 551 | BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, |
552 | centerOfMass, OMV.Quaternion.Identity); | ||
553 | DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", | ||
554 | LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); | ||
554 | foreach (BSPhysObject child in m_taintChildren) | 555 | foreach (BSPhysObject child in m_taintChildren) |
555 | { | 556 | { |
556 | BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); | 557 | BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, |
558 | centerOfMass, OMV.Quaternion.Identity); | ||
557 | } | 559 | } |
560 | |||
561 | // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG | ||
558 | } | 562 | } |
559 | return; | 563 | return; |
560 | } | 564 | } |
@@ -563,7 +567,8 @@ public class BSLinkset | |||
563 | // Invoke the detailed logger and output something if it's enabled. | 567 | // Invoke the detailed logger and output something if it's enabled. |
564 | private void DetailLog(string msg, params Object[] args) | 568 | private void DetailLog(string msg, params Object[] args) |
565 | { | 569 | { |
566 | PhysicsScene.PhysicsLogging.Write(msg, args); | 570 | if (PhysicsScene.PhysicsLogging.Enabled) |
571 | PhysicsScene.DetailLog(msg, args); | ||
567 | } | 572 | } |
568 | 573 | ||
569 | } | 574 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 1ac8c59..cae599c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -85,6 +85,10 @@ public abstract class BSPhysObject : PhysicsActor | |||
85 | 85 | ||
86 | public abstract OMV.Quaternion ForceOrientation { get; set; } | 86 | public abstract OMV.Quaternion ForceOrientation { get; set; } |
87 | 87 | ||
88 | public abstract OMV.Vector3 ForceVelocity { get; set; } | ||
89 | |||
90 | public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } | ||
91 | |||
88 | #region Collisions | 92 | #region Collisions |
89 | 93 | ||
90 | // Requested number of milliseconds between collision events. Zero means disabled. | 94 | // Requested number of milliseconds between collision events. Zero means disabled. |
@@ -207,7 +211,8 @@ public abstract class BSPhysObject : PhysicsActor | |||
207 | // High performance detailed logging routine used by the physical objects. | 211 | // High performance detailed logging routine used by the physical objects. |
208 | protected void DetailLog(string msg, params Object[] args) | 212 | protected void DetailLog(string msg, params Object[] args) |
209 | { | 213 | { |
210 | PhysicsScene.PhysicsLogging.Write(msg, args); | 214 | if (PhysicsScene.PhysicsLogging.Enabled) |
215 | PhysicsScene.DetailLog(msg, args); | ||
211 | } | 216 | } |
212 | } | 217 | } |
213 | } | 218 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index f7b68ba..6a4365c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -196,7 +196,7 @@ public sealed class BSPrim : BSPhysObject | |||
196 | _isSelected = value; | 196 | _isSelected = value; |
197 | PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() | 197 | PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() |
198 | { | 198 | { |
199 | // DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); | 199 | DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); |
200 | SetObjectDynamic(false); | 200 | SetObjectDynamic(false); |
201 | }); | 201 | }); |
202 | } | 202 | } |
@@ -265,6 +265,11 @@ public sealed class BSPrim : BSPhysObject | |||
265 | return _position; | 265 | return _position; |
266 | } | 266 | } |
267 | set { | 267 | set { |
268 | // If you must push the position into the physics engine, use ForcePosition. | ||
269 | if (_position == value) | ||
270 | { | ||
271 | return; | ||
272 | } | ||
268 | _position = value; | 273 | _position = value; |
269 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? | 274 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? |
270 | PositionSanityCheck(); | 275 | PositionSanityCheck(); |
@@ -322,7 +327,7 @@ public sealed class BSPrim : BSPhysObject | |||
322 | // A version of the sanity check that also makes sure a new position value is | 327 | // A version of the sanity check that also makes sure a new position value is |
323 | // pushed back to the physics engine. This routine would be used by anyone | 328 | // pushed back to the physics engine. This routine would be used by anyone |
324 | // who is not already pushing the value. | 329 | // who is not already pushing the value. |
325 | private bool PositionSanityCheck2(bool atTaintTime) | 330 | private bool PositionSanityCheck2(bool inTaintTime) |
326 | { | 331 | { |
327 | bool ret = false; | 332 | bool ret = false; |
328 | if (PositionSanityCheck()) | 333 | if (PositionSanityCheck()) |
@@ -334,7 +339,7 @@ public sealed class BSPrim : BSPhysObject | |||
334 | DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 339 | DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
335 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); | 340 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); |
336 | }; | 341 | }; |
337 | if (atTaintTime) | 342 | if (inTaintTime) |
338 | sanityOperation(); | 343 | sanityOperation(); |
339 | else | 344 | else |
340 | PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); | 345 | PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); |
@@ -453,7 +458,6 @@ public sealed class BSPrim : BSPhysObject | |||
453 | } | 458 | } |
454 | return; | 459 | return; |
455 | } | 460 | } |
456 | |||
457 | public override OMV.Vector3 Velocity { | 461 | public override OMV.Vector3 Velocity { |
458 | get { return _velocity; } | 462 | get { return _velocity; } |
459 | set { | 463 | set { |
@@ -465,6 +469,13 @@ public sealed class BSPrim : BSPhysObject | |||
465 | }); | 469 | }); |
466 | } | 470 | } |
467 | } | 471 | } |
472 | public override OMV.Vector3 ForceVelocity { | ||
473 | get { return _velocity; } | ||
474 | set { | ||
475 | _velocity = value; | ||
476 | BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); | ||
477 | } | ||
478 | } | ||
468 | public override OMV.Vector3 Torque { | 479 | public override OMV.Vector3 Torque { |
469 | get { return _torque; } | 480 | get { return _torque; } |
470 | set { _torque = value; | 481 | set { _torque = value; |
@@ -490,6 +501,8 @@ public sealed class BSPrim : BSPhysObject | |||
490 | return _orientation; | 501 | return _orientation; |
491 | } | 502 | } |
492 | set { | 503 | set { |
504 | if (_orientation == value) | ||
505 | return; | ||
493 | _orientation = value; | 506 | _orientation = value; |
494 | // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? | 507 | // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? |
495 | PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() | 508 | PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() |
@@ -570,7 +583,7 @@ public sealed class BSPrim : BSPhysObject | |||
570 | // Set up the object physicalness (does gravity and collisions move this object) | 583 | // Set up the object physicalness (does gravity and collisions move this object) |
571 | MakeDynamic(IsStatic); | 584 | MakeDynamic(IsStatic); |
572 | 585 | ||
573 | // Update vehicle specific parameters | 586 | // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) |
574 | _vehicle.Refresh(); | 587 | _vehicle.Refresh(); |
575 | 588 | ||
576 | // Arrange for collision events if the simulator wants them | 589 | // Arrange for collision events if the simulator wants them |
@@ -593,7 +606,7 @@ public sealed class BSPrim : BSPhysObject | |||
593 | // Recompute any linkset parameters. | 606 | // Recompute any linkset parameters. |
594 | // When going from non-physical to physical, this re-enables the constraints that | 607 | // When going from non-physical to physical, this re-enables the constraints that |
595 | // had been automatically disabled when the mass was set to zero. | 608 | // had been automatically disabled when the mass was set to zero. |
596 | Linkset.Refresh(this); | 609 | Linkset.Refresh(this, true); |
597 | 610 | ||
598 | DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", | 611 | DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", |
599 | LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); | 612 | LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); |
@@ -620,8 +633,10 @@ public sealed class BSPrim : BSPhysObject | |||
620 | BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); | 633 | BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); |
621 | // There can be special things needed for implementing linksets | 634 | // There can be special things needed for implementing linksets |
622 | Linkset.MakeStatic(this); | 635 | Linkset.MakeStatic(this); |
623 | // The activation state is 'disabled' so Bullet will not try to act on it | 636 | // The activation state is 'disabled' so Bullet will not try to act on it. |
624 | BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); | 637 | BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); |
638 | // Start it out sleeping and physical actions could wake it up. | ||
639 | // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); | ||
625 | 640 | ||
626 | BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; | 641 | BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; |
627 | BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; | 642 | BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; |
@@ -638,6 +653,9 @@ public sealed class BSPrim : BSPhysObject | |||
638 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 | 653 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 |
639 | BulletSimAPI.ClearAllForces2(BSBody.ptr); | 654 | BulletSimAPI.ClearAllForces2(BSBody.ptr); |
640 | 655 | ||
656 | // For good measure, make sure the transform is set through to the motion state | ||
657 | BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); | ||
658 | |||
641 | // A dynamic object has mass | 659 | // A dynamic object has mass |
642 | IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); | 660 | IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); |
643 | OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); | 661 | OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); |
@@ -655,8 +673,8 @@ public sealed class BSPrim : BSPhysObject | |||
655 | 673 | ||
656 | // Force activation of the object so Bullet will act on it. | 674 | // Force activation of the object so Bullet will act on it. |
657 | // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. | 675 | // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. |
658 | BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); | 676 | BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); |
659 | BulletSimAPI.Activate2(BSBody.ptr, true); | 677 | // BulletSimAPI.Activate2(BSBody.ptr, true); |
660 | 678 | ||
661 | BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; | 679 | BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; |
662 | BSBody.collisionMask = CollisionFilterGroups.ObjectMask; | 680 | BSBody.collisionMask = CollisionFilterGroups.ObjectMask; |
@@ -774,6 +792,15 @@ public sealed class BSPrim : BSPhysObject | |||
774 | }); | 792 | }); |
775 | } | 793 | } |
776 | } | 794 | } |
795 | public override OMV.Vector3 ForceRotationalVelocity { | ||
796 | get { | ||
797 | return _rotationalVelocity; | ||
798 | } | ||
799 | set { | ||
800 | _rotationalVelocity = value; | ||
801 | BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); | ||
802 | } | ||
803 | } | ||
777 | public override bool Kinematic { | 804 | public override bool Kinematic { |
778 | get { return _kinematic; } | 805 | get { return _kinematic; } |
779 | set { _kinematic = value; | 806 | set { _kinematic = value; |
@@ -828,6 +855,9 @@ public sealed class BSPrim : BSPhysObject | |||
828 | 855 | ||
829 | private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); | 856 | private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); |
830 | public override void AddForce(OMV.Vector3 force, bool pushforce) { | 857 | public override void AddForce(OMV.Vector3 force, bool pushforce) { |
858 | AddForce(force, pushforce, false); | ||
859 | } | ||
860 | public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { | ||
831 | // for an object, doesn't matter if force is a pushforce or not | 861 | // for an object, doesn't matter if force is a pushforce or not |
832 | if (force.IsFinite()) | 862 | if (force.IsFinite()) |
833 | { | 863 | { |
@@ -840,11 +870,12 @@ public sealed class BSPrim : BSPhysObject | |||
840 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); | 870 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); |
841 | return; | 871 | return; |
842 | } | 872 | } |
843 | PhysicsScene.TaintedObject("BSPrim.AddForce", delegate() | 873 | BSScene.TaintCallback addForceOperation = delegate() |
844 | { | 874 | { |
845 | OMV.Vector3 fSum = OMV.Vector3.Zero; | 875 | OMV.Vector3 fSum = OMV.Vector3.Zero; |
846 | lock (m_accumulatedForces) | 876 | lock (m_accumulatedForces) |
847 | { | 877 | { |
878 | // Sum the accumulated additional forces for one big force to apply once. | ||
848 | foreach (OMV.Vector3 v in m_accumulatedForces) | 879 | foreach (OMV.Vector3 v in m_accumulatedForces) |
849 | { | 880 | { |
850 | fSum += v; | 881 | fSum += v; |
@@ -854,7 +885,11 @@ public sealed class BSPrim : BSPhysObject | |||
854 | // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); | 885 | // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); |
855 | // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. | 886 | // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. |
856 | BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); | 887 | BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); |
857 | }); | 888 | }; |
889 | if (inTaintTime) | ||
890 | addForceOperation(); | ||
891 | else | ||
892 | PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation); | ||
858 | } | 893 | } |
859 | 894 | ||
860 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 895 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { |
@@ -1204,6 +1239,7 @@ public sealed class BSPrim : BSPhysObject | |||
1204 | { | 1239 | { |
1205 | // Called if the current prim body is about to be destroyed. | 1240 | // Called if the current prim body is about to be destroyed. |
1206 | // Remove all the physical dependencies on the old body. | 1241 | // Remove all the physical dependencies on the old body. |
1242 | // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) | ||
1207 | needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); | 1243 | needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); |
1208 | }); | 1244 | }); |
1209 | 1245 | ||
@@ -1294,6 +1330,8 @@ public sealed class BSPrim : BSPhysObject | |||
1294 | 1330 | ||
1295 | PositionSanityCheck2(true); | 1331 | PositionSanityCheck2(true); |
1296 | 1332 | ||
1333 | Linkset.UpdateProperties(this); | ||
1334 | |||
1297 | DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 1335 | DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
1298 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | 1336 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); |
1299 | 1337 | ||
@@ -1304,7 +1342,7 @@ public sealed class BSPrim : BSPhysObject | |||
1304 | /* | 1342 | /* |
1305 | else | 1343 | else |
1306 | { | 1344 | { |
1307 | // For debugging, we can also report the movement of children | 1345 | // For debugging, report the movement of children |
1308 | DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 1346 | DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
1309 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | 1347 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, |
1310 | entprop.Acceleration, entprop.RotationalVelocity); | 1348 | entprop.Acceleration, entprop.RotationalVelocity); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index aaed7de..2c3c481 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -39,7 +39,6 @@ using log4net; | |||
39 | using OpenMetaverse; | 39 | using OpenMetaverse; |
40 | 40 | ||
41 | // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) | 41 | // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) |
42 | // Move all logic out of the C++ code and into the C# code for easier future modifications. | ||
43 | // Test sculpties (verified that they don't work) | 42 | // Test sculpties (verified that they don't work) |
44 | // Compute physics FPS reasonably | 43 | // Compute physics FPS reasonably |
45 | // Based on material, set density and friction | 44 | // Based on material, set density and friction |
@@ -90,10 +89,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
90 | // let my minuions use my logger | 89 | // let my minuions use my logger |
91 | public ILog Logger { get { return m_log; } } | 90 | public ILog Logger { get { return m_log; } } |
92 | 91 | ||
93 | // If non-zero, the number of simulation steps between calls to the physics | ||
94 | // engine to output detailed physics stats. Debug logging level must be on also. | ||
95 | private int m_detailedStatsStep = 0; | ||
96 | |||
97 | public IMesher mesher; | 92 | public IMesher mesher; |
98 | // Level of Detail values kept as float because that's what the Meshmerizer wants | 93 | // Level of Detail values kept as float because that's what the Meshmerizer wants |
99 | public float MeshLOD { get; private set; } | 94 | public float MeshLOD { get; private set; } |
@@ -112,6 +107,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
112 | private float m_fixedTimeStep; | 107 | private float m_fixedTimeStep; |
113 | private long m_simulationStep = 0; | 108 | private long m_simulationStep = 0; |
114 | public long SimulationStep { get { return m_simulationStep; } } | 109 | public long SimulationStep { get { return m_simulationStep; } } |
110 | private int m_taintsToProcessPerStep; | ||
115 | 111 | ||
116 | // A value of the time now so all the collision and update routines do not have to get their own | 112 | // A value of the time now so all the collision and update routines do not have to get their own |
117 | // Set to 'now' just before all the prims and actors are called for collisions and updates | 113 | // Set to 'now' just before all the prims and actors are called for collisions and updates |
@@ -131,6 +127,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
131 | 127 | ||
132 | public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed | 128 | public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed |
133 | public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes | 129 | public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes |
130 | public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects | ||
134 | 131 | ||
135 | public float PID_D { get; private set; } // derivative | 132 | public float PID_D { get; private set; } // derivative |
136 | public float PID_P { get; private set; } // proportional | 133 | public float PID_P { get; private set; } // proportional |
@@ -254,7 +251,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
254 | 251 | ||
255 | // The bounding box for the simulated world. The origin is 0,0,0 unless we're | 252 | // The bounding box for the simulated world. The origin is 0,0,0 unless we're |
256 | // a child in a mega-region. | 253 | // a child in a mega-region. |
257 | // Turns out that Bullet really doesn't care about the extents of the simulated | 254 | // Bullet actually doesn't care about the extents of the simulated |
258 | // area. It tracks active objects no matter where they are. | 255 | // area. It tracks active objects no matter where they are. |
259 | Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); | 256 | Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); |
260 | 257 | ||
@@ -331,7 +328,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
331 | // Called directly from unmanaged code so don't do much | 328 | // Called directly from unmanaged code so don't do much |
332 | private void BulletLoggerPhysLog(string msg) | 329 | private void BulletLoggerPhysLog(string msg) |
333 | { | 330 | { |
334 | PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); | 331 | DetailLog("[BULLETS UNMANAGED]:" + msg); |
335 | } | 332 | } |
336 | 333 | ||
337 | public override void Dispose() | 334 | public override void Dispose() |
@@ -494,8 +491,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
494 | m_simulationStep++; | 491 | m_simulationStep++; |
495 | int numSubSteps = 0; | 492 | int numSubSteps = 0; |
496 | 493 | ||
497 | // Sometimes needed for debugging to find out what happened before the step | 494 | // DEBUG |
498 | // PhysicsLogging.Flush(); | 495 | // DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); |
499 | 496 | ||
500 | try | 497 | try |
501 | { | 498 | { |
@@ -505,8 +502,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
505 | out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); | 502 | out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); |
506 | 503 | ||
507 | if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); | 504 | if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); |
508 | DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}", | 505 | DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", |
509 | DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); | 506 | DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); |
510 | } | 507 | } |
511 | catch (Exception e) | 508 | catch (Exception e) |
512 | { | 509 | { |
@@ -582,19 +579,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
582 | } | 579 | } |
583 | } | 580 | } |
584 | 581 | ||
585 | // If enabled, call into the physics engine to dump statistics | ||
586 | if (m_detailedStatsStep > 0) | ||
587 | { | ||
588 | if ((m_simulationStep % m_detailedStatsStep) == 0) | ||
589 | { | ||
590 | BulletSimAPI.DumpBulletStatistics(); | ||
591 | } | ||
592 | } | ||
593 | |||
594 | // The physics engine returns the number of milliseconds it simulated this call. | 582 | // The physics engine returns the number of milliseconds it simulated this call. |
595 | // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. | 583 | // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. |
596 | // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. | 584 | // We multiply by 45 to give a recognizable running rate (45 or less). |
597 | return numSubSteps * m_fixedTimeStep * 1000; | 585 | return numSubSteps * m_fixedTimeStep * 1000 * 45; |
586 | // return timeStep * 1000 * 45; | ||
598 | } | 587 | } |
599 | 588 | ||
600 | // Something has collided | 589 | // Something has collided |
@@ -617,7 +606,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
617 | BSPhysObject collidee = null; | 606 | BSPhysObject collidee = null; |
618 | PhysObjects.TryGetValue(collidingWith, out collidee); | 607 | PhysObjects.TryGetValue(collidingWith, out collidee); |
619 | 608 | ||
620 | DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); | 609 | // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); |
621 | 610 | ||
622 | if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) | 611 | if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) |
623 | { | 612 | { |
@@ -704,6 +693,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
704 | if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process | 693 | if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process |
705 | { | 694 | { |
706 | // swizzle a new list into the list location so we can process what's there | 695 | // swizzle a new list into the list location so we can process what's there |
696 | int taintCount = m_taintsToProcessPerStep; | ||
697 | TaintCallbackEntry oneCallback = new TaintCallbackEntry(); | ||
698 | while (_taintedObjects.Count > 0 && taintCount-- > 0) | ||
699 | { | ||
700 | bool gotOne = false; | ||
701 | lock (_taintLock) | ||
702 | { | ||
703 | if (_taintedObjects.Count > 0) | ||
704 | { | ||
705 | oneCallback = _taintedObjects[0]; | ||
706 | _taintedObjects.RemoveAt(0); | ||
707 | gotOne = true; | ||
708 | } | ||
709 | } | ||
710 | if (gotOne) | ||
711 | { | ||
712 | try | ||
713 | { | ||
714 | DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG | ||
715 | oneCallback.callback(); | ||
716 | } | ||
717 | catch (Exception e) | ||
718 | { | ||
719 | m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e); | ||
720 | } | ||
721 | } | ||
722 | } | ||
723 | /* | ||
724 | // swizzle a new list into the list location so we can process what's there | ||
707 | List<TaintCallbackEntry> oldList; | 725 | List<TaintCallbackEntry> oldList; |
708 | lock (_taintLock) | 726 | lock (_taintLock) |
709 | { | 727 | { |
@@ -715,6 +733,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
715 | { | 733 | { |
716 | try | 734 | try |
717 | { | 735 | { |
736 | DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG | ||
718 | tcbe.callback(); | 737 | tcbe.callback(); |
719 | } | 738 | } |
720 | catch (Exception e) | 739 | catch (Exception e) |
@@ -723,6 +742,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
723 | } | 742 | } |
724 | } | 743 | } |
725 | oldList.Clear(); | 744 | oldList.Clear(); |
745 | */ | ||
726 | } | 746 | } |
727 | } | 747 | } |
728 | 748 | ||
@@ -834,6 +854,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
834 | (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, | 854 | (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, |
835 | (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, | 855 | (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, |
836 | (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), | 856 | (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), |
857 | new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", | ||
858 | ConfigurationParameters.numericTrue, | ||
859 | (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); }, | ||
860 | (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); }, | ||
861 | (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ), | ||
837 | 862 | ||
838 | new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", | 863 | new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", |
839 | 8f, | 864 | 8f, |
@@ -876,6 +901,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
876 | (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, | 901 | (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, |
877 | (s) => { return (float)s.m_maxUpdatesPerFrame; }, | 902 | (s) => { return (float)s.m_maxUpdatesPerFrame; }, |
878 | (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), | 903 | (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), |
904 | new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", | ||
905 | 100f, | ||
906 | (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, | ||
907 | (s) => { return (float)s.m_taintsToProcessPerStep; }, | ||
908 | (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), | ||
879 | new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", | 909 | new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", |
880 | 10000.01f, | 910 | 10000.01f, |
881 | (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, | 911 | (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, |
@@ -1070,12 +1100,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1070 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, | 1100 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, |
1071 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), | 1101 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), |
1072 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", | 1102 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", |
1073 | 0.1f, | 1103 | 0.001f, |
1074 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, | 1104 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, |
1075 | (s) => { return s.m_params[0].linkConstraintCFM; }, | 1105 | (s) => { return s.m_params[0].linkConstraintCFM; }, |
1076 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), | 1106 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), |
1077 | new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", | 1107 | new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", |
1078 | 0.2f, | 1108 | 0.8f, |
1079 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, | 1109 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, |
1080 | (s) => { return s.m_params[0].linkConstraintERP; }, | 1110 | (s) => { return s.m_params[0].linkConstraintERP; }, |
1081 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), | 1111 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), |
@@ -1085,11 +1115,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1085 | (s) => { return s.m_params[0].linkConstraintSolverIterations; }, | 1115 | (s) => { return s.m_params[0].linkConstraintSolverIterations; }, |
1086 | (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), | 1116 | (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), |
1087 | 1117 | ||
1088 | new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", | 1118 | new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)", |
1089 | 0f, | 1119 | 0f, |
1090 | (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, | 1120 | (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); }, |
1091 | (s) => { return (float)s.m_detailedStatsStep; }, | 1121 | (s) => { return (float)s.m_params[0].physicsLoggingFrames; }, |
1092 | (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), | 1122 | (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ), |
1093 | }; | 1123 | }; |
1094 | 1124 | ||
1095 | // Convert a boolean to our numeric true and false values | 1125 | // Convert a boolean to our numeric true and false values |
@@ -1270,6 +1300,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1270 | public void DetailLog(string msg, params Object[] args) | 1300 | public void DetailLog(string msg, params Object[] args) |
1271 | { | 1301 | { |
1272 | PhysicsLogging.Write(msg, args); | 1302 | PhysicsLogging.Write(msg, args); |
1303 | // Add the Flush() if debugging crashes to get all the messages written out. | ||
1304 | // PhysicsLogging.Flush(); | ||
1273 | } | 1305 | } |
1274 | // used to fill in the LocalID when there isn't one | 1306 | // used to fill in the LocalID when there isn't one |
1275 | public const string DetailLogZero = "0000000000"; | 1307 | public const string DetailLogZero = "0000000000"; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 399a133..d189f1d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | |||
@@ -67,8 +67,8 @@ public class BSShapeCollection : IDisposable | |||
67 | public DateTime lastReferenced; | 67 | public DateTime lastReferenced; |
68 | } | 68 | } |
69 | 69 | ||
70 | private Dictionary<ulong, MeshDesc> Meshes = new Dictionary<ulong, MeshDesc>(); | 70 | private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>(); |
71 | private Dictionary<ulong, HullDesc> Hulls = new Dictionary<ulong, HullDesc>(); | 71 | private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>(); |
72 | private Dictionary<uint, BodyDesc> Bodies = new Dictionary<uint, BodyDesc>(); | 72 | private Dictionary<uint, BodyDesc> Bodies = new Dictionary<uint, BodyDesc>(); |
73 | 73 | ||
74 | public BSShapeCollection(BSScene physScene) | 74 | public BSShapeCollection(BSScene physScene) |
@@ -121,7 +121,7 @@ public class BSShapeCollection : IDisposable | |||
121 | // Track another user of a body | 121 | // Track another user of a body |
122 | // We presume the caller has allocated the body. | 122 | // We presume the caller has allocated the body. |
123 | // Bodies only have one user so the reference count is either 1 or 0. | 123 | // Bodies only have one user so the reference count is either 1 or 0. |
124 | public void ReferenceBody(BulletBody body, bool atTaintTime) | 124 | public void ReferenceBody(BulletBody body, bool inTaintTime) |
125 | { | 125 | { |
126 | lock (m_collectionActivityLock) | 126 | lock (m_collectionActivityLock) |
127 | { | 127 | { |
@@ -136,7 +136,21 @@ public class BSShapeCollection : IDisposable | |||
136 | // New entry | 136 | // New entry |
137 | bodyDesc.ptr = body.ptr; | 137 | bodyDesc.ptr = body.ptr; |
138 | bodyDesc.referenceCount = 1; | 138 | bodyDesc.referenceCount = 1; |
139 | DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", body.ID, body, bodyDesc.referenceCount); | 139 | DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={2}", |
140 | body.ID, body, bodyDesc.referenceCount); | ||
141 | BSScene.TaintCallback createOperation = delegate() | ||
142 | { | ||
143 | if (!BulletSimAPI.IsInWorld2(body.ptr)) | ||
144 | { | ||
145 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); | ||
146 | DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", | ||
147 | body.ID, body); | ||
148 | } | ||
149 | }; | ||
150 | if (inTaintTime) | ||
151 | createOperation(); | ||
152 | else | ||
153 | PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); | ||
140 | } | 154 | } |
141 | bodyDesc.lastReferenced = System.DateTime.Now; | 155 | bodyDesc.lastReferenced = System.DateTime.Now; |
142 | Bodies[body.ID] = bodyDesc; | 156 | Bodies[body.ID] = bodyDesc; |
@@ -160,21 +174,22 @@ public class BSShapeCollection : IDisposable | |||
160 | Bodies[body.ID] = bodyDesc; | 174 | Bodies[body.ID] = bodyDesc; |
161 | DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); | 175 | DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); |
162 | 176 | ||
163 | // If body is no longer being used, free it -- bodies are never shared. | 177 | // If body is no longer being used, free it -- bodies can never be shared. |
164 | if (bodyDesc.referenceCount == 0) | 178 | if (bodyDesc.referenceCount == 0) |
165 | { | 179 | { |
166 | Bodies.Remove(body.ID); | 180 | Bodies.Remove(body.ID); |
167 | BSScene.TaintCallback removeOperation = delegate() | 181 | BSScene.TaintCallback removeOperation = delegate() |
168 | { | 182 | { |
169 | DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", | 183 | DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", |
170 | body.ID, body.ptr.ToString("X")); | 184 | body.ID, body.ptr.ToString("X"), inTaintTime); |
171 | // If the caller needs to know the old body is going away, pass the event up. | 185 | // If the caller needs to know the old body is going away, pass the event up. |
172 | if (bodyCallback != null) bodyCallback(body); | 186 | if (bodyCallback != null) bodyCallback(body); |
173 | 187 | ||
174 | // Zero any reference to the shape so it is not freed when the body is deleted. | ||
175 | BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); | ||
176 | // It may have already been removed from the world in which case the next is a NOOP. | 188 | // It may have already been removed from the world in which case the next is a NOOP. |
177 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); | 189 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); |
190 | |||
191 | // Zero any reference to the shape so it is not freed when the body is deleted. | ||
192 | BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); | ||
178 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); | 193 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); |
179 | }; | 194 | }; |
180 | // If already in taint-time, do the operations now. Otherwise queue for later. | 195 | // If already in taint-time, do the operations now. Otherwise queue for later. |
@@ -208,7 +223,7 @@ public class BSShapeCollection : IDisposable | |||
208 | { | 223 | { |
209 | // There is an existing instance of this mesh. | 224 | // There is an existing instance of this mesh. |
210 | meshDesc.referenceCount++; | 225 | meshDesc.referenceCount++; |
211 | DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}", | 226 | DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", |
212 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); | 227 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); |
213 | } | 228 | } |
214 | else | 229 | else |
@@ -217,7 +232,7 @@ public class BSShapeCollection : IDisposable | |||
217 | meshDesc.ptr = shape.ptr; | 232 | meshDesc.ptr = shape.ptr; |
218 | // We keep a reference to the underlying IMesh data so a hull can be built | 233 | // We keep a reference to the underlying IMesh data so a hull can be built |
219 | meshDesc.referenceCount = 1; | 234 | meshDesc.referenceCount = 1; |
220 | DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}", | 235 | DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", |
221 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); | 236 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); |
222 | ret = true; | 237 | ret = true; |
223 | } | 238 | } |
@@ -230,7 +245,7 @@ public class BSShapeCollection : IDisposable | |||
230 | { | 245 | { |
231 | // There is an existing instance of this hull. | 246 | // There is an existing instance of this hull. |
232 | hullDesc.referenceCount++; | 247 | hullDesc.referenceCount++; |
233 | DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}", | 248 | DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", |
234 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); | 249 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); |
235 | } | 250 | } |
236 | else | 251 | else |
@@ -238,7 +253,7 @@ public class BSShapeCollection : IDisposable | |||
238 | // This is a new reference to a hull | 253 | // This is a new reference to a hull |
239 | hullDesc.ptr = shape.ptr; | 254 | hullDesc.ptr = shape.ptr; |
240 | hullDesc.referenceCount = 1; | 255 | hullDesc.referenceCount = 1; |
241 | DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}", | 256 | DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", |
242 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); | 257 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); |
243 | ret = true; | 258 | ret = true; |
244 | 259 | ||
@@ -257,7 +272,7 @@ public class BSShapeCollection : IDisposable | |||
257 | 272 | ||
258 | // Release the usage of a shape. | 273 | // Release the usage of a shape. |
259 | // The collisionObject is released since it is a copy of the real collision shape. | 274 | // The collisionObject is released since it is a copy of the real collision shape. |
260 | public void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback) | 275 | public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) |
261 | { | 276 | { |
262 | if (shape.ptr == IntPtr.Zero) | 277 | if (shape.ptr == IntPtr.Zero) |
263 | return; | 278 | return; |
@@ -279,14 +294,14 @@ public class BSShapeCollection : IDisposable | |||
279 | if (shape.ptr != IntPtr.Zero & shape.isNativeShape) | 294 | if (shape.ptr != IntPtr.Zero & shape.isNativeShape) |
280 | { | 295 | { |
281 | DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", | 296 | DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", |
282 | BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime); | 297 | BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); |
283 | if (shapeCallback != null) shapeCallback(shape); | 298 | if (shapeCallback != null) shapeCallback(shape); |
284 | BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); | 299 | BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); |
285 | } | 300 | } |
286 | break; | 301 | break; |
287 | } | 302 | } |
288 | }; | 303 | }; |
289 | if (atTaintTime) | 304 | if (inTaintTime) |
290 | { | 305 | { |
291 | lock (m_collectionActivityLock) | 306 | lock (m_collectionActivityLock) |
292 | { | 307 | { |
@@ -358,7 +373,8 @@ public class BSShapeCollection : IDisposable | |||
358 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 | 373 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 |
359 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) | 374 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) |
360 | { | 375 | { |
361 | if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) | 376 | if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) |
377 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) | ||
362 | { | 378 | { |
363 | haveShape = true; | 379 | haveShape = true; |
364 | if (forceRebuild | 380 | if (forceRebuild |
@@ -372,7 +388,7 @@ public class BSShapeCollection : IDisposable | |||
372 | prim.LocalID, forceRebuild, prim.BSShape); | 388 | prim.LocalID, forceRebuild, prim.BSShape); |
373 | } | 389 | } |
374 | } | 390 | } |
375 | else | 391 | if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) |
376 | { | 392 | { |
377 | haveShape = true; | 393 | haveShape = true; |
378 | if (forceRebuild | 394 | if (forceRebuild |
@@ -392,7 +408,7 @@ public class BSShapeCollection : IDisposable | |||
392 | // made. Native shapes are best used in either case. | 408 | // made. Native shapes are best used in either case. |
393 | if (!haveShape) | 409 | if (!haveShape) |
394 | { | 410 | { |
395 | if (prim.IsPhysical) | 411 | if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) |
396 | { | 412 | { |
397 | // Update prim.BSShape to reference a hull of this shape. | 413 | // Update prim.BSShape to reference a hull of this shape. |
398 | ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); | 414 | ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); |
@@ -426,7 +442,7 @@ public class BSShapeCollection : IDisposable | |||
426 | 442 | ||
427 | // Native shapes are always built independently. | 443 | // Native shapes are always built independently. |
428 | newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); | 444 | newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); |
429 | newShape.shapeKey = (ulong)shapeKey; | 445 | newShape.shapeKey = (System.UInt64)shapeKey; |
430 | newShape.isNativeShape = true; | 446 | newShape.isNativeShape = true; |
431 | 447 | ||
432 | // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. | 448 | // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. |
@@ -446,7 +462,7 @@ public class BSShapeCollection : IDisposable | |||
446 | BulletShape newShape = new BulletShape(IntPtr.Zero); | 462 | BulletShape newShape = new BulletShape(IntPtr.Zero); |
447 | 463 | ||
448 | float lod; | 464 | float lod; |
449 | ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); | 465 | System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); |
450 | 466 | ||
451 | // if this new shape is the same as last time, don't recreate the mesh | 467 | // if this new shape is the same as last time, don't recreate the mesh |
452 | if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) | 468 | if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) |
@@ -469,7 +485,7 @@ public class BSShapeCollection : IDisposable | |||
469 | return true; // 'true' means a new shape has been added to this prim | 485 | return true; // 'true' means a new shape has been added to this prim |
470 | } | 486 | } |
471 | 487 | ||
472 | private BulletShape CreatePhysicalMesh(string objName, ulong newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) | 488 | private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) |
473 | { | 489 | { |
474 | IMesh meshData = null; | 490 | IMesh meshData = null; |
475 | IntPtr meshPtr; | 491 | IntPtr meshPtr; |
@@ -516,7 +532,7 @@ public class BSShapeCollection : IDisposable | |||
516 | BulletShape newShape; | 532 | BulletShape newShape; |
517 | 533 | ||
518 | float lod; | 534 | float lod; |
519 | ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod); | 535 | System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod); |
520 | 536 | ||
521 | // if the hull hasn't changed, don't rebuild it | 537 | // if the hull hasn't changed, don't rebuild it |
522 | if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) | 538 | if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) |
@@ -525,7 +541,7 @@ public class BSShapeCollection : IDisposable | |||
525 | DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", | 541 | DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", |
526 | prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); | 542 | prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); |
527 | 543 | ||
528 | // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull. | 544 | // Remove usage of the previous shape. |
529 | DereferenceShape(prim.BSShape, true, shapeCallback); | 545 | DereferenceShape(prim.BSShape, true, shapeCallback); |
530 | 546 | ||
531 | newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); | 547 | newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); |
@@ -539,7 +555,7 @@ public class BSShapeCollection : IDisposable | |||
539 | } | 555 | } |
540 | 556 | ||
541 | List<ConvexResult> m_hulls; | 557 | List<ConvexResult> m_hulls; |
542 | private BulletShape CreatePhysicalHull(string objName, ulong newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) | 558 | private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) |
543 | { | 559 | { |
544 | 560 | ||
545 | IntPtr hullPtr; | 561 | IntPtr hullPtr; |
@@ -652,22 +668,23 @@ public class BSShapeCollection : IDisposable | |||
652 | 668 | ||
653 | // Create a hash of all the shape parameters to be used as a key | 669 | // Create a hash of all the shape parameters to be used as a key |
654 | // for this particular shape. | 670 | // for this particular shape. |
655 | private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) | 671 | private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) |
656 | { | 672 | { |
657 | // level of detail based on size and type of the object | 673 | // level of detail based on size and type of the object |
658 | float lod = PhysicsScene.MeshLOD; | 674 | float lod = PhysicsScene.MeshLOD; |
659 | if (pbs.SculptEntry) | 675 | if (pbs.SculptEntry) |
660 | lod = PhysicsScene.SculptLOD; | 676 | lod = PhysicsScene.SculptLOD; |
661 | 677 | ||
678 | // Mega prims usually get more detail because one can interact with shape approximations at this size. | ||
662 | float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); | 679 | float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); |
663 | if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) | 680 | if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) |
664 | lod = PhysicsScene.MeshMegaPrimLOD; | 681 | lod = PhysicsScene.MeshMegaPrimLOD; |
665 | 682 | ||
666 | retLod = lod; | 683 | retLod = lod; |
667 | return (ulong)pbs.GetMeshKey(shapeData.Size, lod); | 684 | return pbs.GetMeshKey(shapeData.Size, lod); |
668 | } | 685 | } |
669 | // For those who don't want the LOD | 686 | // For those who don't want the LOD |
670 | private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) | 687 | private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) |
671 | { | 688 | { |
672 | float lod; | 689 | float lod; |
673 | return ComputeShapeKey(shapeData, pbs, out lod); | 690 | return ComputeShapeKey(shapeData, pbs, out lod); |
@@ -701,6 +718,7 @@ public class BSShapeCollection : IDisposable | |||
701 | 718 | ||
702 | if (mustRebuild || forceRebuild) | 719 | if (mustRebuild || forceRebuild) |
703 | { | 720 | { |
721 | // Free any old body | ||
704 | DereferenceBody(prim.BSBody, true, bodyCallback); | 722 | DereferenceBody(prim.BSBody, true, bodyCallback); |
705 | 723 | ||
706 | BulletBody aBody; | 724 | BulletBody aBody; |
@@ -709,13 +727,13 @@ public class BSShapeCollection : IDisposable | |||
709 | { | 727 | { |
710 | bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, | 728 | bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, |
711 | shapeData.ID, shapeData.Position, shapeData.Rotation); | 729 | shapeData.ID, shapeData.Position, shapeData.Rotation); |
712 | // DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); | 730 | DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); |
713 | } | 731 | } |
714 | else | 732 | else |
715 | { | 733 | { |
716 | bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, | 734 | bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, |
717 | shapeData.ID, shapeData.Position, shapeData.Rotation); | 735 | shapeData.ID, shapeData.Position, shapeData.Rotation); |
718 | // DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); | 736 | DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); |
719 | } | 737 | } |
720 | aBody = new BulletBody(shapeData.ID, bodyPtr); | 738 | aBody = new BulletBody(shapeData.ID, bodyPtr); |
721 | 739 | ||
@@ -731,7 +749,8 @@ public class BSShapeCollection : IDisposable | |||
731 | 749 | ||
732 | private void DetailLog(string msg, params Object[] args) | 750 | private void DetailLog(string msg, params Object[] args) |
733 | { | 751 | { |
734 | PhysicsScene.PhysicsLogging.Write(msg, args); | 752 | if (PhysicsScene.PhysicsLogging.Enabled) |
753 | PhysicsScene.DetailLog(msg, args); | ||
735 | } | 754 | } |
736 | } | 755 | } |
737 | } | 756 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 70aa429..caf411e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | |||
@@ -114,6 +114,8 @@ public class BSTerrainManager | |||
114 | BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, | 114 | BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, |
115 | Vector3.Zero, Quaternion.Identity)); | 115 | Vector3.Zero, Quaternion.Identity)); |
116 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); | 116 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); |
117 | // Ground plane does not move | ||
118 | BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); | ||
117 | // Everything collides with the ground plane. | 119 | // Everything collides with the ground plane. |
118 | BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, | 120 | BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, |
119 | (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); | 121 | (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); |
@@ -201,10 +203,10 @@ public class BSTerrainManager | |||
201 | // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when | 203 | // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when |
202 | // calling this routine from initialization or taint-time routines) or whether to delay | 204 | // calling this routine from initialization or taint-time routines) or whether to delay |
203 | // all the unmanaged activities to taint-time. | 205 | // all the unmanaged activities to taint-time. |
204 | private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool atTaintTime) | 206 | private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) |
205 | { | 207 | { |
206 | DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},atTaintTime={3}", | 208 | DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", |
207 | BSScene.DetailLogZero, minCoords, maxCoords, atTaintTime); | 209 | BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); |
208 | 210 | ||
209 | float minZ = float.MaxValue; | 211 | float minZ = float.MaxValue; |
210 | float maxZ = float.MinValue; | 212 | float maxZ = float.MinValue; |
@@ -296,16 +298,16 @@ public class BSTerrainManager | |||
296 | mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, | 298 | mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, |
297 | mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); | 299 | mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); |
298 | 300 | ||
301 | // Create the terrain shape from the mapInfo | ||
302 | mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), | ||
303 | ShapeData.PhysicsShapeType.SHAPE_TERRAIN); | ||
304 | |||
299 | // The terrain object initial position is at the center of the object | 305 | // The terrain object initial position is at the center of the object |
300 | Vector3 centerPos; | 306 | Vector3 centerPos; |
301 | centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); | 307 | centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); |
302 | centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); | 308 | centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); |
303 | centerPos.Z = minZ + ((maxZ - minZ) / 2f); | 309 | centerPos.Z = minZ + ((maxZ - minZ) / 2f); |
304 | 310 | ||
305 | // Create the terrain shape from the mapInfo | ||
306 | mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), | ||
307 | ShapeData.PhysicsShapeType.SHAPE_TERRAIN); | ||
308 | |||
309 | mapInfo.terrainBody = new BulletBody(mapInfo.ID, | 311 | mapInfo.terrainBody = new BulletBody(mapInfo.ID, |
310 | BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, | 312 | BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, |
311 | id, centerPos, Quaternion.Identity)); | 313 | id, centerPos, Quaternion.Identity)); |
@@ -320,9 +322,6 @@ public class BSTerrainManager | |||
320 | BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); | 322 | BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); |
321 | BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); | 323 | BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); |
322 | 324 | ||
323 | BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, 0f, Vector3.Zero); | ||
324 | BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.ptr); | ||
325 | |||
326 | // Return the new terrain to the world of physical objects | 325 | // Return the new terrain to the world of physical objects |
327 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); | 326 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); |
328 | 327 | ||
@@ -342,7 +341,7 @@ public class BSTerrainManager | |||
342 | 341 | ||
343 | // There is the option to do the changes now (we're already in 'taint time'), or | 342 | // There is the option to do the changes now (we're already in 'taint time'), or |
344 | // to do the Bullet operations later. | 343 | // to do the Bullet operations later. |
345 | if (atTaintTime) | 344 | if (inTaintTime) |
346 | rebuildOperation(); | 345 | rebuildOperation(); |
347 | else | 346 | else |
348 | PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); | 347 | PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); |
@@ -381,7 +380,7 @@ public class BSTerrainManager | |||
381 | }; | 380 | }; |
382 | 381 | ||
383 | // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. | 382 | // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. |
384 | if (atTaintTime) | 383 | if (inTaintTime) |
385 | createOperation(); | 384 | createOperation(); |
386 | else | 385 | else |
387 | PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); | 386 | PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index a43880d..276111c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -101,9 +101,8 @@ public struct BulletShape | |||
101 | } | 101 | } |
102 | public IntPtr ptr; | 102 | public IntPtr ptr; |
103 | public ShapeData.PhysicsShapeType type; | 103 | public ShapeData.PhysicsShapeType type; |
104 | public ulong shapeKey; | 104 | public System.UInt64 shapeKey; |
105 | public bool isNativeShape; | 105 | public bool isNativeShape; |
106 | // Hulls have an underlying mesh. A pointer to it is hidden here. | ||
107 | public override string ToString() | 106 | public override string ToString() |
108 | { | 107 | { |
109 | StringBuilder buff = new StringBuilder(); | 108 | StringBuilder buff = new StringBuilder(); |
@@ -192,8 +191,9 @@ public struct ShapeData | |||
192 | SHAPE_SPHERE = 5, | 191 | SHAPE_SPHERE = 5, |
193 | SHAPE_MESH = 6, | 192 | SHAPE_MESH = 6, |
194 | SHAPE_HULL = 7, | 193 | SHAPE_HULL = 7, |
195 | SHAPE_GROUNDPLANE = 8, | 194 | // following defined by BulletSim |
196 | SHAPE_TERRAIN = 9, | 195 | SHAPE_GROUNDPLANE = 20, |
196 | SHAPE_TERRAIN = 21, | ||
197 | }; | 197 | }; |
198 | public uint ID; | 198 | public uint ID; |
199 | public PhysicsShapeType Type; | 199 | public PhysicsShapeType Type; |
@@ -305,6 +305,8 @@ public struct ConfigurationParameters | |||
305 | public float linkConstraintCFM; | 305 | public float linkConstraintCFM; |
306 | public float linkConstraintSolverIterations; | 306 | public float linkConstraintSolverIterations; |
307 | 307 | ||
308 | public float physicsLoggingFrames; | ||
309 | |||
308 | public const float numericTrue = 1f; | 310 | public const float numericTrue = 1f; |
309 | public const float numericFalse = 0f; | 311 | public const float numericFalse = 0f; |
310 | } | 312 | } |
@@ -1037,18 +1039,6 @@ public static extern IntPtr GetConstraintRef2(IntPtr obj, int index); | |||
1037 | public static extern int GetNumConstraintRefs2(IntPtr obj); | 1039 | public static extern int GetNumConstraintRefs2(IntPtr obj); |
1038 | 1040 | ||
1039 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 1041 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1040 | public static extern Vector3 GetDeltaLinearVelocity2(IntPtr obj); | ||
1041 | |||
1042 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1043 | public static extern Vector3 GetDeltaAngularVelocity2(IntPtr obj); | ||
1044 | |||
1045 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1046 | public static extern Vector3 GetPushVelocity2(IntPtr obj); | ||
1047 | |||
1048 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1049 | public static extern Vector3 GetTurnVelocity2(IntPtr obj); | ||
1050 | |||
1051 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1052 | public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); | 1042 | public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); |
1053 | 1043 | ||
1054 | // ===================================================================================== | 1044 | // ===================================================================================== |
@@ -1108,6 +1098,15 @@ public static extern float GetMargin2(IntPtr shape); | |||
1108 | public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); | 1098 | public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); |
1109 | 1099 | ||
1110 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 1100 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1101 | public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape); | ||
1102 | |||
1103 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1104 | public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain); | ||
1105 | |||
1106 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1107 | public static extern void DumpAllInfo2(IntPtr sim); | ||
1108 | |||
1109 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1111 | public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); | 1110 | public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); |
1112 | 1111 | ||
1113 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 1112 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index f3b0630..c736557 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | |||
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
100 | private bool m_hackSentFly = false; | 100 | private bool m_hackSentFly = false; |
101 | private int m_requestedUpdateFrequency = 0; | 101 | private int m_requestedUpdateFrequency = 0; |
102 | private Vector3 m_taintPosition; | 102 | private Vector3 m_taintPosition; |
103 | 103 | internal bool m_avatarplanted = false; | |
104 | /// <summary> | 104 | /// <summary> |
105 | /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force | 105 | /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force |
106 | /// while calculatios are going on | 106 | /// while calculatios are going on |
@@ -413,7 +413,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
413 | set | 413 | set |
414 | { | 414 | { |
415 | m_iscollidingObj = value; | 415 | m_iscollidingObj = value; |
416 | if (value) | 416 | if (value && !m_avatarplanted) |
417 | m_pidControllerActive = false; | 417 | m_pidControllerActive = false; |
418 | else | 418 | else |
419 | m_pidControllerActive = true; | 419 | m_pidControllerActive = true; |
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 7a50c4c..cbe21e2 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs | |||
@@ -501,6 +501,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
501 | public int physics_logging_interval = 0; | 501 | public int physics_logging_interval = 0; |
502 | public bool physics_logging_append_existing_logfile = false; | 502 | public bool physics_logging_append_existing_logfile = false; |
503 | 503 | ||
504 | private bool avplanted = false; | ||
505 | private bool av_av_collisions_off = false; | ||
504 | 506 | ||
505 | public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); | 507 | public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); |
506 | public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); | 508 | public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); |
@@ -644,6 +646,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
644 | avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); | 646 | avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); |
645 | avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); | 647 | avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); |
646 | avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); | 648 | avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); |
649 | avplanted = physicsconfig.GetBoolean("av_planted", false); | ||
650 | av_av_collisions_off = physicsconfig.GetBoolean("av_av_collisions_off", false); | ||
651 | |||
647 | IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); | 652 | IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); |
648 | 653 | ||
649 | contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); | 654 | contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); |
@@ -663,6 +668,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
663 | meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); | 668 | meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); |
664 | MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); | 669 | MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); |
665 | m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); | 670 | m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); |
671 | |||
672 | |||
666 | 673 | ||
667 | if (Environment.OSVersion.Platform == PlatformID.Unix) | 674 | if (Environment.OSVersion.Platform == PlatformID.Unix) |
668 | { | 675 | { |
@@ -1309,6 +1316,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1309 | if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) | 1316 | if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) |
1310 | skipThisContact = true; // No collision on volume detect prims | 1317 | skipThisContact = true; // No collision on volume detect prims |
1311 | 1318 | ||
1319 | if (av_av_collisions_off) | ||
1320 | if ((p1 is OdeCharacter) && (p2 is OdeCharacter)) | ||
1321 | skipThisContact = true; | ||
1322 | |||
1312 | if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) | 1323 | if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) |
1313 | skipThisContact = true; // No collision on volume detect prims | 1324 | skipThisContact = true; // No collision on volume detect prims |
1314 | 1325 | ||
@@ -1972,7 +1983,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1972 | 1983 | ||
1973 | newAv.Flying = isFlying; | 1984 | newAv.Flying = isFlying; |
1974 | newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; | 1985 | newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; |
1975 | 1986 | newAv.m_avatarplanted = avplanted; | |
1987 | |||
1976 | return newAv; | 1988 | return newAv; |
1977 | } | 1989 | } |
1978 | 1990 | ||
@@ -1987,6 +1999,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1987 | 1999 | ||
1988 | internal void AddCharacter(OdeCharacter chr) | 2000 | internal void AddCharacter(OdeCharacter chr) |
1989 | { | 2001 | { |
2002 | chr.m_avatarplanted = avplanted; | ||
1990 | if (!_characters.Contains(chr)) | 2003 | if (!_characters.Contains(chr)) |
1991 | { | 2004 | { |
1992 | _characters.Add(chr); | 2005 | _characters.Add(chr); |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 2c682d4..17277d7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | |||
@@ -3600,7 +3600,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3600 | /// <returns></returns> | 3600 | /// <returns></returns> |
3601 | public void osSetContentType(LSL_Key id, string type) | 3601 | public void osSetContentType(LSL_Key id, string type) |
3602 | { | 3602 | { |
3603 | CheckThreatLevel(ThreatLevel.High,"osSetResponseType"); | 3603 | CheckThreatLevel(ThreatLevel.High, "osSetContentType"); |
3604 | |||
3604 | if (m_UrlModule != null) | 3605 | if (m_UrlModule != null) |
3605 | m_UrlModule.HttpContentType(new UUID(id),type); | 3606 | m_UrlModule.HttpContentType(new UUID(id),type); |
3606 | } | 3607 | } |
@@ -3611,7 +3612,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3611 | /// <returns>boolean indicating whether an error was shouted.</returns> | 3612 | /// <returns>boolean indicating whether an error was shouted.</returns> |
3612 | protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix) | 3613 | protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix) |
3613 | { | 3614 | { |
3614 | CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); | ||
3615 | m_host.AddScriptLPS(1); | 3615 | m_host.AddScriptLPS(1); |
3616 | bool fail = false; | 3616 | bool fail = false; |
3617 | if (m_item.PermsGranter != m_host.OwnerID) | 3617 | if (m_item.PermsGranter != m_host.OwnerID) |
diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs index 21fb678..45c13fb 100644 --- a/OpenSim/Server/ServerMain.cs +++ b/OpenSim/Server/ServerMain.cs | |||
@@ -60,7 +60,25 @@ namespace OpenSim.Server | |||
60 | } | 60 | } |
61 | 61 | ||
62 | string connList = serverConfig.GetString("ServiceConnectors", String.Empty); | 62 | string connList = serverConfig.GetString("ServiceConnectors", String.Empty); |
63 | string[] conns = connList.Split(new char[] {',', ' '}); | 63 | |
64 | IConfig servicesConfig = m_Server.Config.Configs["ServiceList"]; | ||
65 | if (servicesConfig != null) | ||
66 | { | ||
67 | List<string> servicesList = new List<string>(); | ||
68 | if (connList != String.Empty) | ||
69 | servicesList.Add(connList); | ||
70 | |||
71 | foreach (string k in servicesConfig.GetKeys()) | ||
72 | { | ||
73 | string v = servicesConfig.GetString(k); | ||
74 | if (v != String.Empty) | ||
75 | servicesList.Add(v); | ||
76 | } | ||
77 | |||
78 | connList = String.Join(",", servicesList.ToArray()); | ||
79 | } | ||
80 | |||
81 | string[] conns = connList.Split(new char[] {',', ' ', '\n', '\r', '\t'}); | ||
64 | 82 | ||
65 | // int i = 0; | 83 | // int i = 0; |
66 | foreach (string c in conns) | 84 | foreach (string c in conns) |
@@ -130,4 +148,4 @@ namespace OpenSim.Server | |||
130 | return 0; | 148 | return 0; |
131 | } | 149 | } |
132 | } | 150 | } |
133 | } \ No newline at end of file | 151 | } |
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index 67a10b0..20eaa3a 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs | |||
@@ -395,8 +395,8 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
395 | if (response["Success"].AsBoolean()) | 395 | if (response["Success"].AsBoolean()) |
396 | { | 396 | { |
397 | OSDMap extraData = response["ExtraData"] as OSDMap; | 397 | OSDMap extraData = response["ExtraData"] as OSDMap; |
398 | int enabled = response["Enabled"].AsBoolean() ? (int) OpenSim.Data.RegionFlags.RegionOnline : 0; | 398 | int enabled = response["Enabled"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.RegionOnline : 0; |
399 | int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int) OpenSim.Data.RegionFlags.Hyperlink : 0; | 399 | int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.Hyperlink : 0; |
400 | int flags = enabled | hypergrid; | 400 | int flags = enabled | hypergrid; |
401 | m_log.DebugFormat("[SGGC] enabled - {0} hg - {1} flags - {2}", enabled, hypergrid, flags); | 401 | m_log.DebugFormat("[SGGC] enabled - {0} hg - {1} flags - {2}", enabled, hypergrid, flags); |
402 | return flags; | 402 | return flags; |
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index 5bdea06..ee3b858 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs | |||
@@ -151,11 +151,11 @@ namespace OpenSim.Services.GridService | |||
151 | // | 151 | // |
152 | // Get it's flags | 152 | // Get it's flags |
153 | // | 153 | // |
154 | OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(region.Data["flags"]); | 154 | OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(region.Data["flags"]); |
155 | 155 | ||
156 | // Is this a reservation? | 156 | // Is this a reservation? |
157 | // | 157 | // |
158 | if ((rflags & OpenSim.Data.RegionFlags.Reservation) != 0) | 158 | if ((rflags & OpenSim.Framework.RegionFlags.Reservation) != 0) |
159 | { | 159 | { |
160 | // Regions reserved for the null key cannot be taken. | 160 | // Regions reserved for the null key cannot be taken. |
161 | if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString()) | 161 | if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString()) |
@@ -166,10 +166,10 @@ namespace OpenSim.Services.GridService | |||
166 | // NOTE: Fudging the flags value here, so these flags | 166 | // NOTE: Fudging the flags value here, so these flags |
167 | // should not be used elsewhere. Don't optimize | 167 | // should not be used elsewhere. Don't optimize |
168 | // this with the later retrieval of the same flags! | 168 | // this with the later retrieval of the same flags! |
169 | rflags |= OpenSim.Data.RegionFlags.Authenticate; | 169 | rflags |= OpenSim.Framework.RegionFlags.Authenticate; |
170 | } | 170 | } |
171 | 171 | ||
172 | if ((rflags & OpenSim.Data.RegionFlags.Authenticate) != 0) | 172 | if ((rflags & OpenSim.Framework.RegionFlags.Authenticate) != 0) |
173 | { | 173 | { |
174 | // Can we authenticate at all? | 174 | // Can we authenticate at all? |
175 | // | 175 | // |
@@ -205,10 +205,10 @@ namespace OpenSim.Services.GridService | |||
205 | if ((region != null) && (region.RegionID == regionInfos.RegionID) && | 205 | if ((region != null) && (region.RegionID == regionInfos.RegionID) && |
206 | ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY))) | 206 | ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY))) |
207 | { | 207 | { |
208 | if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0) | 208 | if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.NoMove) != 0) |
209 | return "Can't move this region"; | 209 | return "Can't move this region"; |
210 | 210 | ||
211 | if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.LockedOut) != 0) | 211 | if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.LockedOut) != 0) |
212 | return "Region locked out"; | 212 | return "Region locked out"; |
213 | 213 | ||
214 | // Region reregistering in other coordinates. Delete the old entry | 214 | // Region reregistering in other coordinates. Delete the old entry |
@@ -233,7 +233,7 @@ namespace OpenSim.Services.GridService | |||
233 | { | 233 | { |
234 | int oldFlags = Convert.ToInt32(region.Data["flags"]); | 234 | int oldFlags = Convert.ToInt32(region.Data["flags"]); |
235 | 235 | ||
236 | oldFlags &= ~(int)OpenSim.Data.RegionFlags.Reservation; | 236 | oldFlags &= ~(int)OpenSim.Framework.RegionFlags.Reservation; |
237 | 237 | ||
238 | rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags | 238 | rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags |
239 | } | 239 | } |
@@ -252,7 +252,7 @@ namespace OpenSim.Services.GridService | |||
252 | } | 252 | } |
253 | 253 | ||
254 | int flags = Convert.ToInt32(rdata.Data["flags"]); | 254 | int flags = Convert.ToInt32(rdata.Data["flags"]); |
255 | flags |= (int)OpenSim.Data.RegionFlags.RegionOnline; | 255 | flags |= (int)OpenSim.Framework.RegionFlags.RegionOnline; |
256 | rdata.Data["flags"] = flags.ToString(); | 256 | rdata.Data["flags"] = flags.ToString(); |
257 | 257 | ||
258 | try | 258 | try |
@@ -283,9 +283,9 @@ namespace OpenSim.Services.GridService | |||
283 | 283 | ||
284 | int flags = Convert.ToInt32(region.Data["flags"]); | 284 | int flags = Convert.ToInt32(region.Data["flags"]); |
285 | 285 | ||
286 | if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Data.RegionFlags.Persistent) != 0) | 286 | if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Framework.RegionFlags.Persistent) != 0) |
287 | { | 287 | { |
288 | flags &= ~(int)OpenSim.Data.RegionFlags.RegionOnline; | 288 | flags &= ~(int)OpenSim.Framework.RegionFlags.RegionOnline; |
289 | region.Data["flags"] = flags.ToString(); | 289 | region.Data["flags"] = flags.ToString(); |
290 | region.Data["last_seen"] = Util.UnixTimeSinceEpoch(); | 290 | region.Data["last_seen"] = Util.UnixTimeSinceEpoch(); |
291 | try | 291 | try |
@@ -320,7 +320,7 @@ namespace OpenSim.Services.GridService | |||
320 | if (rdata.RegionID != regionID) | 320 | if (rdata.RegionID != regionID) |
321 | { | 321 | { |
322 | int flags = Convert.ToInt32(rdata.Data["flags"]); | 322 | int flags = Convert.ToInt32(rdata.Data["flags"]); |
323 | if ((flags & (int)Data.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours | 323 | if ((flags & (int)Framework.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours |
324 | rinfos.Add(RegionData2RegionInfo(rdata)); | 324 | rinfos.Add(RegionData2RegionInfo(rdata)); |
325 | } | 325 | } |
326 | } | 326 | } |
@@ -470,7 +470,7 @@ namespace OpenSim.Services.GridService | |||
470 | 470 | ||
471 | foreach (RegionData r in regions) | 471 | foreach (RegionData r in regions) |
472 | { | 472 | { |
473 | if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0) | 473 | if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0) |
474 | ret.Add(RegionData2RegionInfo(r)); | 474 | ret.Add(RegionData2RegionInfo(r)); |
475 | } | 475 | } |
476 | 476 | ||
@@ -486,7 +486,7 @@ namespace OpenSim.Services.GridService | |||
486 | 486 | ||
487 | foreach (RegionData r in regions) | 487 | foreach (RegionData r in regions) |
488 | { | 488 | { |
489 | if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0) | 489 | if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0) |
490 | ret.Add(RegionData2RegionInfo(r)); | 490 | ret.Add(RegionData2RegionInfo(r)); |
491 | } | 491 | } |
492 | 492 | ||
@@ -502,7 +502,7 @@ namespace OpenSim.Services.GridService | |||
502 | 502 | ||
503 | foreach (RegionData r in regions) | 503 | foreach (RegionData r in regions) |
504 | { | 504 | { |
505 | if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0) | 505 | if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0) |
506 | ret.Add(RegionData2RegionInfo(r)); | 506 | ret.Add(RegionData2RegionInfo(r)); |
507 | } | 507 | } |
508 | 508 | ||
@@ -629,7 +629,7 @@ namespace OpenSim.Services.GridService | |||
629 | 629 | ||
630 | private void OutputRegionToConsole(RegionData r) | 630 | private void OutputRegionToConsole(RegionData r) |
631 | { | 631 | { |
632 | OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); | 632 | OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]); |
633 | 633 | ||
634 | ConsoleDisplayList dispList = new ConsoleDisplayList(); | 634 | ConsoleDisplayList dispList = new ConsoleDisplayList(); |
635 | dispList.AddRow("Region Name", r.RegionName); | 635 | dispList.AddRow("Region Name", r.RegionName); |
@@ -659,7 +659,7 @@ namespace OpenSim.Services.GridService | |||
659 | 659 | ||
660 | foreach (RegionData r in regions) | 660 | foreach (RegionData r in regions) |
661 | { | 661 | { |
662 | OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); | 662 | OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]); |
663 | dispTable.AddRow( | 663 | dispTable.AddRow( |
664 | r.RegionName, | 664 | r.RegionName, |
665 | r.RegionID.ToString(), | 665 | r.RegionID.ToString(), |
@@ -673,7 +673,7 @@ namespace OpenSim.Services.GridService | |||
673 | 673 | ||
674 | private int ParseFlags(int prev, string flags) | 674 | private int ParseFlags(int prev, string flags) |
675 | { | 675 | { |
676 | OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)prev; | 676 | OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)prev; |
677 | 677 | ||
678 | string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries); | 678 | string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries); |
679 | 679 | ||
@@ -685,18 +685,18 @@ namespace OpenSim.Services.GridService | |||
685 | { | 685 | { |
686 | if (p.StartsWith("+")) | 686 | if (p.StartsWith("+")) |
687 | { | 687 | { |
688 | val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1)); | 688 | val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1)); |
689 | f |= (OpenSim.Data.RegionFlags)val; | 689 | f |= (OpenSim.Framework.RegionFlags)val; |
690 | } | 690 | } |
691 | else if (p.StartsWith("-")) | 691 | else if (p.StartsWith("-")) |
692 | { | 692 | { |
693 | val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1)); | 693 | val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1)); |
694 | f &= ~(OpenSim.Data.RegionFlags)val; | 694 | f &= ~(OpenSim.Framework.RegionFlags)val; |
695 | } | 695 | } |
696 | else | 696 | else |
697 | { | 697 | { |
698 | val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p); | 698 | val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p); |
699 | f |= (OpenSim.Data.RegionFlags)val; | 699 | f |= (OpenSim.Framework.RegionFlags)val; |
700 | } | 700 | } |
701 | } | 701 | } |
702 | catch (Exception) | 702 | catch (Exception) |
@@ -728,7 +728,7 @@ namespace OpenSim.Services.GridService | |||
728 | int flags = Convert.ToInt32(r.Data["flags"]); | 728 | int flags = Convert.ToInt32(r.Data["flags"]); |
729 | flags = ParseFlags(flags, cmd[4]); | 729 | flags = ParseFlags(flags, cmd[4]); |
730 | r.Data["flags"] = flags.ToString(); | 730 | r.Data["flags"] = flags.ToString(); |
731 | OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)flags; | 731 | OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)flags; |
732 | 732 | ||
733 | MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f)); | 733 | MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f)); |
734 | m_Database.Store(r); | 734 | m_Database.Store(r); |
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 78eab3d..743d089 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs | |||
@@ -390,8 +390,8 @@ namespace OpenSim.Services.GridService | |||
390 | List<RegionData> regions = m_Database.Get(mapName, m_ScopeID); | 390 | List<RegionData> regions = m_Database.Get(mapName, m_ScopeID); |
391 | if (regions != null && regions.Count > 0) | 391 | if (regions != null && regions.Count > 0) |
392 | { | 392 | { |
393 | OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]); | 393 | OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]); |
394 | if ((rflags & OpenSim.Data.RegionFlags.Hyperlink) != 0) | 394 | if ((rflags & OpenSim.Framework.RegionFlags.Hyperlink) != 0) |
395 | { | 395 | { |
396 | regInfo = new GridRegion(); | 396 | regInfo = new GridRegion(); |
397 | regInfo.RegionID = regions[0].RegionID; | 397 | regInfo.RegionID = regions[0].RegionID; |
@@ -460,7 +460,7 @@ namespace OpenSim.Services.GridService | |||
460 | private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle) | 460 | private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle) |
461 | { | 461 | { |
462 | RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo); | 462 | RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo); |
463 | int flags = (int)OpenSim.Data.RegionFlags.Hyperlink + (int)OpenSim.Data.RegionFlags.NoDirectLogin + (int)OpenSim.Data.RegionFlags.RegionOnline; | 463 | int flags = (int)OpenSim.Framework.RegionFlags.Hyperlink + (int)OpenSim.Framework.RegionFlags.NoDirectLogin + (int)OpenSim.Framework.RegionFlags.RegionOnline; |
464 | rdata.Data["flags"] = flags.ToString(); | 464 | rdata.Data["flags"] = flags.ToString(); |
465 | 465 | ||
466 | m_Database.Store(rdata); | 466 | m_Database.Store(rdata); |
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index cdcb961..3f4c958 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs | |||
@@ -100,6 +100,19 @@ namespace OpenSim.Services.Interfaces | |||
100 | List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y); | 100 | List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y); |
101 | List<GridRegion> GetHyperlinks(UUID scopeID); | 101 | List<GridRegion> GetHyperlinks(UUID scopeID); |
102 | 102 | ||
103 | /// <summary> | ||
104 | /// Get internal OpenSimulator region flags. | ||
105 | /// </summary> | ||
106 | /// <remarks> | ||
107 | /// See OpenSimulator.Framework.RegionFlags. These are not returned in the GridRegion structure - | ||
108 | /// they currently need to be requested separately. Possibly this should change to avoid multiple service calls | ||
109 | /// in some situations. | ||
110 | /// </remarks> | ||
111 | /// <returns> | ||
112 | /// The region flags. | ||
113 | /// </returns> | ||
114 | /// <param name='scopeID'></param> | ||
115 | /// <param name='regionID'></param> | ||
103 | int GetRegionFlags(UUID scopeID, UUID regionID); | 116 | int GetRegionFlags(UUID scopeID, UUID regionID); |
104 | } | 117 | } |
105 | 118 | ||